@orkestrel/agent 0.0.35 → 0.0.36

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.
@@ -1,4 +1,5 @@
1
1
  import { ArrayShape } from '@orkestrel/contract';
2
+ import type { AuditFault } from '@orkestrel/contract';
2
3
  import { BooleanShape } from '@orkestrel/contract';
3
4
  import type { BudgetInterface } from '@orkestrel/budget';
4
5
  import { ContractInterface } from '@orkestrel/contract';
@@ -12,9 +13,11 @@ import type { FileInput } from '@orkestrel/workspace';
12
13
  import type { FileInterface } from '@orkestrel/workspace';
13
14
  import type { Guard } from '@orkestrel/contract';
14
15
  import type { JSONRecord } from '@orkestrel/contract';
16
+ import type { JSONSchema } from '@orkestrel/contract';
15
17
  import { JSONShape } from '@orkestrel/contract';
16
18
  import { JSONValue } from '@orkestrel/contract';
17
19
  import { LiteralShape } from '@orkestrel/contract';
20
+ import { NullableShape } from '@orkestrel/contract';
18
21
  import { NumberShape } from '@orkestrel/contract';
19
22
  import { ObjectShape } from '@orkestrel/contract';
20
23
  import { OptionalShape } from '@orkestrel/contract';
@@ -510,13 +513,16 @@ export declare interface AgentContextOptions {
510
513
  }
511
514
 
512
515
  /**
513
- * Reports an `ask` on an authority that has no approver or that its approver refuses, a run sharing accounting or a conversation with a live run, a `limit` that is not a nonnegative safe integer, a name absent from a registry pool, or a strict run whose request exceeds its window. Agent construction, the `stream` and `generate` methods, and registry accessors throw synchronously, before returning a handle or promise; a `'WINDOW'` refusal rejects the run's `result` instead, and an `'APPROVER'` refusal rejects the promise the `ask` method of an `Authority` or the `ask` handler of an `Approver` returns. Await the call inside `try`/`catch` to catch it.
516
+ * Reports an `ask` on an authority that has no approver or that its approver refuses, an authority missing its fallback or a rule's verdict, tools set with no authority, a run sharing accounting or a conversation with a live run, a `limit` that is not a positive safe integer, a name absent from a registry pool, a strict run's answer that fails its schema, or a strict run whose request exceeds its window. Agent construction, the `stream` and `generate` methods, and registry accessors throw synchronously, before returning a handle or promise; a `'WINDOW'` refusal rejects the run's `result` instead, and an `'APPROVER'` refusal rejects the promise the `ask` method of an `Authority` or the `ask` handler of an `Approver` returns. Await the call inside `try`/`catch` to catch it.
514
517
  *
515
518
  * @remarks
516
519
  * `'APPROVER'` reports an `ask` on an `Authority` built with no `ask` handler, or an ask an
517
520
  * `Approver` refuses: a call framed while no ask waited for it, a second ask for a waiting call, or
518
521
  * arguments it cannot render. The agent loop reads it as an unanswered ask and denies the call. Its
519
522
  * `context` names the asked `tool`.
523
+ * `'AUTHORITY'` reports an `Authority` built with no valid `fallback`, a rule with no valid `verdict`
524
+ * (its `context` names the `rule` index), and an agent built with `tools` and no `authority`. Each
525
+ * throws at construction, with the options a host passes to correct it in the message.
520
526
  * `'CONCURRENCY'` reports a run started while another run on the same agent is live, when the
521
527
  * agent carries a `window` (a shared context budget) or when the run's effective `budget` or
522
528
  * `allowance` is an instance a live run holds — the second run's `start()` would replace that
@@ -525,17 +531,18 @@ export declare interface AgentContextOptions {
525
531
  * `agent` id, and the `conversation` id for a shared conversation. For concurrent runs, use
526
532
  * separate agents, or one agent with no `window`, distinct budget and allowance instances per
527
533
  * run, and a distinct conversation per run.
528
- * `'LIMIT'` reports a construction or per-run `limit` that is not a nonnegative safe integer,
534
+ * `'LIMIT'` reports a construction or per-run `limit` that is not a positive safe integer,
529
535
  * including one a rehydrated job carries into `build`. `'REGISTRY'` reports a rehydration name
530
- * absent from its registry pool, on `provider` / `tool` / `authority` / `scheduler` / `build`;
531
- * its `context` names the `category` and the `name`. `'WINDOW'` reports a `strict` run whose
536
+ * absent from its registry pool, on `provider` / `tool` / `authority` / `scheduler` / `build`,
537
+ * whose `context` names the `category` and the `name`, and a job that names `tools` and no
538
+ * `authority` at `build`, whose `context` names the `tools`. `'WINDOW'` reports a `strict` run whose
532
539
  * complete provider request is still over the `window` budget, equal to its `max` included, after
533
540
  * the one permitted fold or with no fold possible; it settles the run `error` before the provider
534
541
  * is called, and its `context` holds the `agent` id, the measured `consumed`, and the window `max`.
535
542
  * Narrow a caught value with {@link isAgentError} and branch on `error.code`.
536
543
  */
537
544
  export declare class AgentError extends Error {
538
- /** Names the machine-readable condition — `'APPROVER'`: an `ask` on an authority that has no approver, or one its approver refuses; `'CONCURRENCY'`: a run sharing accounting or a conversation with a live run; `'LIMIT'`: a `limit` that is not a nonnegative safe integer; `'REGISTRY'`: a rehydration name absent from its registry pool; `'WINDOW'`: a strict run whose complete request is still over its window budget. */
545
+ /** Names the machine-readable condition — `'APPROVER'`: an `ask` on an authority that has no approver, or one its approver refuses; `'AUTHORITY'`: an authority missing its fallback or a rule's verdict, or tools set with no authority; `'CONCURRENCY'`: a run sharing accounting or a conversation with a live run; `'LIMIT'`: a `limit` that is not a positive safe integer; `'REGISTRY'`: a rehydration name absent from its registry pool; `'WINDOW'`: a strict run whose complete request is still over its window budget. */
539
546
  readonly code: AgentErrorCode;
540
547
  /** Holds the values that locate the failure, such as the `agent` id of a refused run, or `undefined` when none were supplied. */
541
548
  readonly context: Readonly<Record<string, unknown>> | undefined;
@@ -549,8 +556,8 @@ export declare class AgentError extends Error {
549
556
  constructor(code: AgentErrorCode, message: string, options?: CodedErrorOptions);
550
557
  }
551
558
 
552
- /** Names the machine-readable agent approver, concurrency, limit, registry, and window failures. */
553
- export declare type AgentErrorCode = 'APPROVER' | 'CONCURRENCY' | 'LIMIT' | 'REGISTRY' | 'WINDOW';
559
+ /** Names the machine-readable agent approver, authority, concurrency, limit, registry, schema, and window failures. */
560
+ export declare type AgentErrorCode = 'APPROVER' | 'AUTHORITY' | 'CONCURRENCY' | 'LIMIT' | 'REGISTRY' | 'SCHEMA' | 'WINDOW';
554
561
 
555
562
  /**
556
563
  * Maps the push observation surface of an {@link AgentInterface} — the lifecycle, usage, and tool
@@ -608,12 +615,11 @@ export declare type AgentEventMap = {
608
615
  readonly ask: readonly [call: ToolCall, decision: AuthorityDecision];
609
616
  /**
610
617
  * Reports a call denied by scope or authority, before dispatch; `decision` is absent for a scope
611
- * miss, a call whose name no definition advertises this turn, a no-advertisement drop, an evaluate
612
- * throw, an invalid decision, or a cleared call whose tool instance changed before dispatch.
613
- * A turn advertising no tools drops each call with `no tool is advertised in the active scope`.
614
- * Otherwise a call excluded by the tool allow-list, or whose name no definition advertises this
615
- * turn, carries `<tool name> is not in the active scope` and produces a denial tool result and
616
- * message. Authority evaluates only admitted calls that name an advertised definition. `reason` is
618
+ * miss, a call whose name no definition advertises this turn, an evaluate throw, an invalid
619
+ * decision, a call on an agent that holds no authority, or a cleared call whose tool instance
620
+ * changed before dispatch. A call excluded by the tool allow-list, or whose name no definition
621
+ * advertises this turn, a turn advertising no tools included, carries `<tool name> is not in the
622
+ * active scope` and produces a denial tool result and message. Authority evaluates only admitted calls that name an advertised definition. `reason` is
617
623
  * the rule's `deny` reason, the thrown error's text, `invalid decision`, `<tool name> changed after
618
624
  * its decision` for a cleared call whose tool instance changed before dispatch (the model reads the
619
625
  * `denied` note), or `undefined`. A cancel that ends the turn before dispatch emits no such `deny`.
@@ -898,7 +904,7 @@ export declare interface AgentInterface {
898
904
  * A run started while another is live throws an {@link import('./errors.js').AgentError} with
899
905
  * `code: 'CONCURRENCY'` when the agent carries a `window`, when the run's effective
900
906
  * `budget` or `allowance` is an instance a live run holds, or when a live run is bound to the
901
- * run's conversation; a run whose `limit` is not a nonnegative safe
907
+ * run's conversation; a run whose `limit` is not a positive safe
902
908
  * integer throws one with `code: 'LIMIT'`. A `prompt` that `agentPromptContract` refuses, a
903
909
  * `budget` or `allowance` that does not implement `BudgetInterface`, or a `conversation` that
904
910
  * does not implement `ConversationInterface`, throws a `ContractError` with code `'placement'`
@@ -910,7 +916,7 @@ export declare interface AgentInterface {
910
916
  *
911
917
  * @param options - Optional per-run {@link AgentRunOptions} (for example `think`); omitted ⇒ defaults
912
918
  * @returns The settled {@link AgentResult} (`partial: true` when cancelled)
913
- * @throws {AgentError} Thrown when a live run shares the `window`, a budget or allowance instance, or the run's conversation (`code: 'CONCURRENCY'`) or the `limit` is not a nonnegative safe integer (`code: 'LIMIT'`), synchronously before a handle returns.
919
+ * @throws {AgentError} Thrown when a live run shares the `window`, a budget or allowance instance, or the run's conversation (`code: 'CONCURRENCY'`) or the `limit` is not a positive safe integer (`code: 'LIMIT'`), synchronously before a handle returns.
914
920
  * @throws {ContractError} Thrown when the `prompt` is not an exact `AgentPrompt`, the `budget` or `allowance` does not implement `BudgetInterface`, or the `conversation` does not implement `ConversationInterface` (`code: 'placement'`), synchronously before a handle returns.
915
921
  */
916
922
  generate(options?: AgentRunOptions): Promise<AgentResult>;
@@ -922,7 +928,7 @@ export declare interface AgentInterface {
922
928
  * @remarks
923
929
  * Like `generate()`, a run that would share the `window`, a live run's budget or allowance
924
930
  * instance, or a live run's conversation throws an {@link import('./errors.js').AgentError} with
925
- * `code: 'CONCURRENCY'`, an invalid `limit` throws one with `code: 'LIMIT'`, and a `prompt` that
931
+ * `code: 'CONCURRENCY'`, a `limit` that is not a positive safe integer throws one with `code: 'LIMIT'`, and a `prompt` that
926
932
  * `agentPromptContract` refuses, a `budget` or `allowance` that does not implement
927
933
  * `BudgetInterface`, or a `conversation` that does not implement `ConversationInterface` throws a
928
934
  * `ContractError` with code `'placement'`, synchronously — before the
@@ -937,7 +943,7 @@ export declare interface AgentInterface {
937
943
  *
938
944
  * @param options - Optional per-run {@link AgentRunOptions} (for example `think`); omitted ⇒ defaults
939
945
  * @returns A live {@link AgentStreamInterface} handle (events + result + abort)
940
- * @throws {AgentError} Thrown when a live run shares the `window`, a budget or allowance instance, or the run's conversation (`code: 'CONCURRENCY'`) or the `limit` is not a nonnegative safe integer (`code: 'LIMIT'`), synchronously before a handle returns.
946
+ * @throws {AgentError} Thrown when a live run shares the `window`, a budget or allowance instance, or the run's conversation (`code: 'CONCURRENCY'`) or the `limit` is not a positive safe integer (`code: 'LIMIT'`), synchronously before a handle returns.
941
947
  * @throws {ContractError} Thrown when the `prompt` is not an exact `AgentPrompt`, the `budget` or `allowance` does not implement `BudgetInterface`, or the `conversation` does not implement `ConversationInterface` (`code: 'placement'`), synchronously before a handle returns.
942
948
  */
943
949
  stream(options?: AgentRunOptions): AgentStreamInterface;
@@ -950,6 +956,37 @@ export declare interface AgentInterface {
950
956
  abort(reason?: unknown): void;
951
957
  }
952
958
 
959
+ /** Checks a durable agent job exactly at `AgentRegistry.build`. */
960
+ export declare const agentJobContract: ContractInterface<Readonly<{
961
+ provider: string;
962
+ } & {
963
+ messages?: readonly Readonly<{
964
+ role: "assistant" | "system" | "tool" | "user";
965
+ content: string;
966
+ } & {
967
+ calls?: readonly Readonly<{
968
+ id: string;
969
+ name: string;
970
+ arguments: {
971
+ readonly [k: string]: JSONValue;
972
+ };
973
+ } & {}>[];
974
+ call?: string;
975
+ images?: readonly string[];
976
+ thinking?: string;
977
+ }>[];
978
+ system?: string;
979
+ tools?: readonly string[];
980
+ authority?: string;
981
+ scheduler?: string;
982
+ limit?: number;
983
+ timeout?: number;
984
+ budget?: number;
985
+ children?: readonly {
986
+ readonly [k: string]: JSONValue;
987
+ }[];
988
+ }>>;
989
+
953
990
  /**
954
991
  * Reports an {@link AgentInterface} run that ended {@link AgentResult.partial} under a
955
992
  * `partial` policy of `false` (the default) — thrown by an agent-job handler (a
@@ -995,13 +1032,13 @@ export declare class AgentJobError extends Error {
995
1032
  export declare interface AgentJobInput {
996
1033
  /** Names the registry key of the {@link ProviderInterface} the job runs against. */
997
1034
  readonly provider: string;
998
- /** Holds the seed conversation added to the rehydrated agent's context (serializable). */
999
- readonly messages: readonly MessageInput[];
1035
+ /** Holds the seed conversation added to the rehydrated agent's context (serializable). Default: an empty seed. */
1036
+ readonly messages?: readonly MessageInput[];
1000
1037
  /** Holds an optional system prompt seeding the agent's context. */
1001
1038
  readonly system?: string;
1002
- /** Names the registry keys of the values of {@link ToolInterface} loaded into the agent's tool manager. */
1039
+ /** Names the registry keys of the values of {@link ToolInterface} loaded into the agent's tool manager; a non-empty list requires `authority`. */
1003
1040
  readonly tools?: readonly string[];
1004
- /** Names the registry key of an optional {@link AuthorityInterface} policy gate. */
1041
+ /** Names the registry key of the {@link AuthorityInterface} policy gate; required when `tools` names any. */
1005
1042
  readonly authority?: string;
1006
1043
  /** Names the registry key of an optional {@link SchedulerInterface} pacing the loop. */
1007
1044
  readonly scheduler?: string;
@@ -1021,6 +1058,39 @@ export declare interface AgentJobInput {
1021
1058
  readonly children?: readonly AgentJobInput[];
1022
1059
  }
1023
1060
 
1061
+ /**
1062
+ * Describes a durable agent job — the record `AgentRegistry.build` checks exactly, so a misspelled key
1063
+ * refuses instead of running an agent without it.
1064
+ *
1065
+ * @remarks
1066
+ * `children` holds JSON records, because each child crosses this shape at its own `build`. `limit`
1067
+ * reads as a number here and as a positive safe integer at the agent's construction, which owns that
1068
+ * refusal.
1069
+ */
1070
+ export declare const agentJobShape: ObjectShape< {
1071
+ provider: StringShape;
1072
+ messages: OptionalShape<ArrayShape<ObjectShape< {
1073
+ role: LiteralShape<readonly ["system", "user", "assistant", "tool"]>;
1074
+ content: StringShape;
1075
+ calls: OptionalShape<ArrayShape<ObjectShape< {
1076
+ id: StringShape;
1077
+ name: StringShape;
1078
+ arguments: ObjectShape<Record<never, never>, JSONShape>;
1079
+ }, boolean | ContractShape>>>;
1080
+ call: OptionalShape<StringShape>;
1081
+ images: OptionalShape<ArrayShape<StringShape>>;
1082
+ thinking: OptionalShape<StringShape>;
1083
+ }, boolean | ContractShape>>>;
1084
+ system: OptionalShape<StringShape>;
1085
+ tools: OptionalShape<ArrayShape<StringShape>>;
1086
+ authority: OptionalShape<StringShape>;
1087
+ scheduler: OptionalShape<StringShape>;
1088
+ limit: OptionalShape<NumberShape>;
1089
+ timeout: OptionalShape<NumberShape>;
1090
+ budget: OptionalShape<NumberShape>;
1091
+ children: OptionalShape<ArrayShape<ObjectShape<Record<never, never>, JSONShape>>>;
1092
+ }, boolean | ContractShape>;
1093
+
1024
1094
  /**
1025
1095
  * Implements the bounded HTTP calls, validation, and result merging of a judge behind concrete
1026
1096
  * wire seams.
@@ -1031,7 +1101,9 @@ export declare interface AgentJobInput {
1031
1101
  * order. `ask` validates the request before any call, builds every body before the first call so
1032
1102
  * a wire limit refuses the request before inference, and runs the calls one after another, each
1033
1103
  * under its own deadline folded with the caller's signal. A cancel throws a `JudgeAbortError`
1034
- * whose `partial` merges the calls that completed. A transport error reaches the caller unchanged.
1104
+ * whose `partial` merges the calls that completed. A transport error reaches the caller unchanged. An
1105
+ * answer that does not fit its question throws code `PROTOCOL`, and a call whose `read` reports no
1106
+ * usage bills the estimate of its response text.
1035
1107
  *
1036
1108
  * @example Writing a judge wire
1037
1109
  * ```ts
@@ -1201,9 +1273,8 @@ export declare interface AgentOptions {
1201
1273
  * Each turn snapshots the scope's tool allow-list before advertising and checks calls
1202
1274
  * against that list before applying authority. A call whose name no definition advertises is
1203
1275
  * denied the same way, whatever the authority would decide.
1204
- * A reply to a turn advertising no tools ends the run as its answer, records an assistant
1205
- * message without calls, and emits a `deny` event for every dropped call without marking it partial.
1206
- * Other scoped-out calls produce denial tool results and messages, and the loop continues.
1276
+ * Every scoped-out call, one in a turn advertising no tools included, produces a denial tool
1277
+ * result and message and a `deny` event, and the loop continues.
1207
1278
  * A scope change through the context's `apply` method applies the tool allow-list at the next
1208
1279
  * turn's snapshot, which a `turn` listener reaches for the same turn, and the instructions,
1209
1280
  * skills, memos, files, and `select` at the next build or select site: run entry, the pre-first-turn
@@ -1211,7 +1282,7 @@ export declare interface AgentOptions {
1211
1282
  */
1212
1283
  readonly scope?: ScopeInterface;
1213
1284
  /**
1214
- * Caps the tool-iteration turns before the loop stops, as a nonnegative safe integer.
1285
+ * Caps the tool-iteration turns before the loop stops, as a positive safe integer.
1215
1286
  * Thrown as an `AgentError` with code `'LIMIT'` when it is not. Default: `DEFAULT_AGENT_LIMIT`.
1216
1287
  */
1217
1288
  readonly limit?: number;
@@ -1248,14 +1319,14 @@ export declare interface AgentOptions {
1248
1319
  /** Carries an external cancel; its abort commits a partial result. */
1249
1320
  readonly signal?: AbortSignal;
1250
1321
  /**
1251
- * Holds an optional policy gate consulted after scope admits a tool call — a denied call is
1322
+ * Holds the policy gate consulted after scope admits a tool call — a denied call is
1252
1323
  * fed back to the model as a denial {@link ToolResult} (a `tool` chunk + a tool
1253
1324
  * message) rather than executed (no tool execution), so the model receives the
1254
1325
  * denial and can react; an allowed call dispatches normally, and an asked call dispatches only
1255
1326
  * when the authority's `ask` approves it. The loop raises an `allow` for a tool whose advertised
1256
- * definition is annotated `consequential` to an `ask`, with or without this option. Omitted ⇒ a
1257
- * default `Authority` with no rules and no approver: an unannotated call dispatches with an
1258
- * `allow` in zone `'default'`, and a `consequential` call is denied as unanswered.
1327
+ * definition is annotated `consequential` to an `ask`. Required when `tools` is set: construction
1328
+ * throws an `AgentError` coded `'AUTHORITY'` otherwise. Omitted with no `tools` ⇒ no gate, and a
1329
+ * tool added later through `context.tools` is denied rather than run.
1259
1330
  */
1260
1331
  readonly authority?: AuthorityInterface;
1261
1332
  /**
@@ -1293,10 +1364,12 @@ export declare interface AgentOptions {
1293
1364
  * still finds over the window, equal to `max` included, after the one permitted fold, or that
1294
1365
  * cannot fold, is refused before the provider is called: the run settles `error` with an
1295
1366
  * `AgentError` coded `'WINDOW'` whose `context` holds the `agent`, the measured `consumed`, and
1296
- * the window `max`, and no `fault` fires for it. If `false`, the run continues — over-window
1297
- * after a summarizer failure or a futile fold, and on the run's conversation's `view()` after a
1298
- * selection fault. A cancel at a selection site or a fold, a `fault` listener's included, settles
1299
- * partial instead of `error`. Default: `false`.
1367
+ * the window `max`, and no `fault` fires for it. A final answer that misses the run's `schema`
1368
+ * settles `error` with an `AgentError` coded `'SCHEMA'`. If `false`, the run continues —
1369
+ * over-window after a summarizer failure or a futile fold, on the run's conversation's `view()`
1370
+ * after a selection fault, and with the raw content after a schema miss, which emits `fault`. A
1371
+ * cancel at a selection site or a fold, a `fault` listener's included, settles partial instead of
1372
+ * `error`. Default: `true`.
1300
1373
  */
1301
1374
  readonly strict?: boolean;
1302
1375
  /**
@@ -1346,7 +1419,8 @@ images: OptionalShape<ArrayShape<StringShape>>;
1346
1419
  * have no size limit. A qwen3 implicit-open reclassification corrects the final
1347
1420
  * content while content deltas already yielded cannot be recalled. A subclass fills
1348
1421
  * `name`, `frame`, `encode`, `read`, and `finish`; the constructor takes the `split`
1349
- * and `strict` switches to control reasoning separation and settled-result requirements.
1422
+ * and `strict` switches to control reasoning separation and whether a stream must end with a settled
1423
+ * `result` or a `done` record, which it must by default.
1350
1424
  * The `replay` input names which stored thinking the agent and relay send back. Default: `'none'`.
1351
1425
  * A throw from the framing seam (`parse`, or `finish`) becomes a `ProviderError` with the
1352
1426
  * `PROTOCOL` code whose `cause` is the throw, unless it is already a `ProviderError` or
@@ -1378,7 +1452,8 @@ images: OptionalShape<ArrayShape<StringShape>>;
1378
1452
  * class TextProvider extends AgentProvider<string> {
1379
1453
  * readonly name = 'text'
1380
1454
  * constructor(options: TextOptions) {
1381
- * super({ ...options, path: '/generate' })
1455
+ * // Raw text has no terminal record, so a stream that stops reads as complete.
1456
+ * super({ ...options, path: '/generate', strict: false })
1382
1457
  * }
1383
1458
  * frame(): ProviderParserInterface<string> {
1384
1459
  * return new TextFrame()
@@ -1443,8 +1518,9 @@ export declare abstract class AgentProvider<TRecord = Readonly<Record<string, un
1443
1518
  * @remarks
1444
1519
  * `path` appends to `url`. If `split` is true, separates in-content reasoning;
1445
1520
  * if false, preserves content verbatim. Default: true.
1446
- * If `strict` is true, requires a settled result record; if false, assembles at end of input.
1447
- * Default: false.
1521
+ * If `strict` is true, a stream that ends with neither a settled `result` nor a `done` record throws
1522
+ * a `ProviderError` with the `PROTOCOL` code, because it was cut; if false, assembles at end of input,
1523
+ * which a wire with no terminal record passes. Default: true.
1448
1524
  */
1449
1525
  export declare interface AgentProviderInput extends ProviderOptions {
1450
1526
  readonly url: string;
@@ -1509,13 +1585,14 @@ export declare interface AgentQueueOptions {
1509
1585
  * rehydrated job is a programmer / config error that must fail loudly at build time, never
1510
1586
  * silently resolve to `undefined` and run an agent missing a dependency.
1511
1587
  * - **`build` rehydrates.** Resolve the job's `provider`; assemble a fresh
1512
- * {@link ToolManager} from the `tools` names; rebuild the token `budget` from its
1588
+ * {@link ToolManager} from the `tools` names, which refuses with `code: 'REGISTRY'` when the job
1589
+ * names no `authority`; rebuild the token `budget` from its
1513
1590
  * ceiling (`createTokenBudget({ max })`); resolve the optional `authority` /
1514
1591
  * `scheduler` names; construct the {@link Agent} with `system` / `limit` / `timeout` /
1515
1592
  * the threaded `signal`; seed its context with the job's `messages`; return it. The
1516
1593
  * `signal` is the queue attempt's / runner unit's cancel, so a bounded abort propagates
1517
1594
  * into the agent (which commits a partial — the job's `partial` policy then
1518
- * decides success vs. retry). A job `limit` that is not a nonnegative safe integer throws an
1595
+ * decides success vs. retry). A job `limit` that is not a positive safe integer throws an
1519
1596
  * {@link AgentError} carrying `code: 'LIMIT'` from the agent's construction.
1520
1597
  * - **Event-free.** A pure resolver — no Emitter, no events.
1521
1598
  *
@@ -1598,7 +1675,7 @@ export declare interface AgentRegistryInterface {
1598
1675
  * @param input - The serializable {@link AgentJobInput} to rehydrate
1599
1676
  * @param signal - An optional cancel threaded into the agent (a queue / runner abort)
1600
1677
  * @returns The ready agent, its context seeded with the job's messages
1601
- * @throws {AgentError} Thrown when a referenced provider, tool, authority, or scheduler name is unregistered (`code: 'REGISTRY'`), or when the job's `limit` is not a nonnegative safe integer (`code: 'LIMIT'`)
1678
+ * @throws {AgentError} Thrown when a referenced provider, tool, authority, or scheduler name is unregistered, or the job names `tools` and no `authority` (`code: 'REGISTRY'`), or when the job's `limit` is not a nonnegative safe integer (`code: 'LIMIT'`)
1602
1679
  * @throws {ConversationError} Thrown when a seed message's role is not a `ConversationRole` (`code: 'ROLE'`), before the agent is returned
1603
1680
  */
1604
1681
  build(input: AgentJobInput, signal?: AbortSignal): AgentInterface;
@@ -1640,7 +1717,7 @@ export declare interface AgentRegistryOptions {
1640
1717
  * holding unresolved tool intent (the model requested tools on the very last allowed
1641
1718
  * turn) — a distinct, non-cancel cause covered by {@link AgentRunResult.exhausted} (see
1642
1719
  * the `exhaust` {@link AgentEventMap} event). It is `false` for a turn that ran to a
1643
- * natural finish (including a `limit: 0` run, which never enters the loop). `usage` is
1720
+ * natural finish. `usage` is
1644
1721
  * present only when at least one provider call or selection reported usage — an aborted run's `usage`
1645
1722
  * includes the cancelled turn's tokens when the provider reports partial usage on the
1646
1723
  * abort (folded in exactly like a completed turn's); a provider that cannot observe
@@ -1702,16 +1779,16 @@ export declare function agentResultToFrame(result: AgentResult): Extract<AgentFr
1702
1779
  /**
1703
1780
  * Projects an unknown value onto a fresh, exact `JSONValue` representation of an
1704
1781
  * {@link AgentResult} — capturing each structural field once through a total boundary,
1705
- * accepting conforming accessors and inherited properties, preserving finite negative and
1706
- * fractional usage counts, dropping extras, and resolving `undefined` for a malformed field, a
1707
- * non-finite usage number, a throwing getter, or a malformed or revoked proxy.
1782
+ * accepting conforming accessors and inherited properties, preserving fractional usage counts,
1783
+ * dropping extras, and resolving `undefined` for a malformed field, a negative or non-finite usage
1784
+ * number, a throwing getter, or a malformed or revoked proxy.
1708
1785
  *
1709
1786
  * @remarks
1710
1787
  * This is a total projection that reads untrusted input. Each structural field is captured once
1711
1788
  * through Contract's sanctioned exception boundary, so conforming accessors and inherited
1712
1789
  * properties are supported while a throwing getter or revoked proxy returns `undefined`.
1713
- * Present usage counts must be finite numbers; negative and fractional values are preserved,
1714
- * not normalized. The result is exact `{ content, thinking?, usage?, partial, stop? }`. A present
1790
+ * Present usage counts must be finite and nonnegative; fractional values are preserved, not
1791
+ * normalized. The result is exact `{ content, thinking?, usage?, partial, stop? }`. A present
1715
1792
  * `stop` is read once, then its `layer`, `id`, `max`, `consumed`, `estimate`, and `usage` once each
1716
1793
  * in that order, `max` and `consumed` only on a `meter` or `budget` arm; the arm is rebuilt
1717
1794
  * exactly, omitting absent readings, and a malformed `stop` refuses the whole value. Extra input
@@ -1776,13 +1853,18 @@ export declare interface AgentRunOptions {
1776
1853
  readonly think?: boolean;
1777
1854
  /**
1778
1855
  * Constrains the response to this JSON-Schema shape, forwarded to the provider's `stream`
1779
- * as {@link ProviderStreamOptions.schema} — a per-run structured-output request. Omitted ⇒
1780
- * no constraint (the loop sends no schema).
1856
+ * as {@link ProviderStreamOptions.schema} — a per-run structured-output request, and enforced: the
1857
+ * final answer must parse as JSON and satisfy the schema, through the lenient `schemaToShape`. A
1858
+ * miss under {@link AgentOptions.strict} settles the run `error` with an `AgentError` coded
1859
+ * `'SCHEMA'` whose `context` holds the `faults` and stores no answer; under `strict: false` it emits
1860
+ * `fault` with that error and settles with the raw content, the opt-out for a provider that ignores
1861
+ * schemas. A `truncated` answer skips the check and keeps its `model` stop. Omitted ⇒ no constraint
1862
+ * (the loop sends no schema).
1781
1863
  */
1782
1864
  readonly schema?: Readonly<Record<string, unknown>>;
1783
1865
  /**
1784
1866
  * Overrides {@link AgentOptions.limit} for this run only — the max tool-iteration turns
1785
- * before the loop stops, as a nonnegative safe integer; the call throws an `AgentError` with
1867
+ * before the loop stops, as a positive safe integer; the call throws an `AgentError` with
1786
1868
  * code `'LIMIT'` when it is not. Omitted ⇒ the agent's constructed `limit` applies.
1787
1869
  */
1788
1870
  readonly limit?: number;
@@ -1925,7 +2007,11 @@ export declare type AgentStreamInterface = StreamInterface<AgentChunk, AgentResu
1925
2007
  * @example
1926
2008
  * ```ts
1927
2009
  * const approver = createApprover()
1928
- * const authority = createAuthority({ rules, ask: approver.ask })
2010
+ * const authority = createAuthority({
2011
+ * rules,
2012
+ * fallback: { zone: 'default', verdict: 'deny' },
2013
+ * ask: approver.ask,
2014
+ * })
1929
2015
  * const agent = createAgent(provider, { tools, authority })
1930
2016
  * for await (const frame of agentStreamToFrames(agent.stream({ prompt }), approver)) {
1931
2017
  * send(JSON.stringify(frame))
@@ -1993,7 +2079,11 @@ export declare interface AnswerMeasure {
1993
2079
  * @example
1994
2080
  * ```ts
1995
2081
  * const approver = new Approver()
1996
- * const authority = createAuthority({ rules, ask: approver.ask })
2082
+ * const authority = createAuthority({
2083
+ * rules,
2084
+ * fallback: { zone: 'default', verdict: 'deny' },
2085
+ * ask: approver.ask,
2086
+ * })
1997
2087
  * approver.answer({ id, approved: true }) // true while that ask waits
1998
2088
  * ```
1999
2089
  */
@@ -2112,13 +2202,14 @@ export declare function attachImages(message: Message, payloads: readonly string
2112
2202
  * @remarks
2113
2203
  * Pure and total: the conversation and its messages are never mutated, and the returned array
2114
2204
  * replaces exactly the one target message with the copy {@link attachImages} builds. Empty
2115
- * data returns the conversation unchanged; a conversation with no user message returns it
2116
- * unchanged too (there is nowhere to attach, so the images are left out). A hole
2117
- * in a sparse conversation is not a user message.
2205
+ * data returns the conversation unchanged. Data with no user message to carry it refuses, an empty
2206
+ * conversation included, because leaving the images out would run without them. A hole in a sparse
2207
+ * conversation is not a user message.
2118
2208
  *
2119
2209
  * @param conversation - The messages to attach into (left unchanged)
2120
2210
  * @param payloads - The base64 image data to attach
2121
2211
  * @returns The conversation with its last user message replaced by the carrying copy
2212
+ * @throws ContextError Thrown when there is data and no user message to carry it (code `'IMAGES'`)
2122
2213
  *
2123
2214
  * @example
2124
2215
  * ```ts
@@ -2131,19 +2222,18 @@ export declare function attachUserImages(conversation: readonly Message[], paylo
2131
2222
  /**
2132
2223
  * Gates the agent loop's tool calls — the synchronous policy consulted before each call runs,
2133
2224
  * turning one {@link AuthorityContext} into an {@link AuthorityDecision} by walking the ordered
2134
- * rules first-match-wins and falling back to a configurable default, which allows an unmatched
2135
- * call unless its `fallback` decides otherwise, and the approver that answers an `ask` verdict.
2225
+ * rules first-match-wins and falling back to the required `fallback`, and the approver that answers
2226
+ * an `ask` verdict.
2136
2227
  *
2137
2228
  * @remarks
2229
+ * - **Refuses at construction.** The constructor throws an `AgentError` coded `'AUTHORITY'` when the
2230
+ * `fallback` is missing or malformed, or when a rule has no valid `verdict`, so a policy with a
2231
+ * hole in it never runs.
2138
2232
  * - **Ordered, first-match-wins.** `evaluate` walks the configured rules in order and
2139
- * returns the first whose `match(context)` is true as
2140
- * `{ zone, verdict: rule.verdict ?? 'allow', reason }` — a matched rule with no `verdict`
2141
- * allows.
2142
- * - **Fallback.** When no rule matches, `evaluate` returns the configured `fallback`.
2143
- * Default: `{ zone: DEFAULT_AUTHORITY_ZONE, verdict: 'allow' }` (allow-unmatched),
2144
- * so a rules list of denials behaves as a denylist. To make the gate deny-by-default
2145
- * (an allowlist — only matched rules that allow get through), pass a `verdict: 'deny'`
2146
- * `fallback`.
2233
+ * returns the first whose `match(context)` is true as `{ zone, verdict, reason }`.
2234
+ * - **Fallback.** When no rule matches, `evaluate` returns the configured `fallback`: a
2235
+ * `verdict: 'deny'` fallback makes an allowlist (only matched rules that allow get through), and a
2236
+ * `verdict: 'allow'` fallback makes a denylist.
2147
2237
  * - **Consulted before each tool call.** The agent loop calls `evaluate({ call })` for
2148
2238
  * every {@link import('@orkestrel/tool').ToolCall} the model emits; a denied call is fed
2149
2239
  * back to the model as a denial {@link import('@orkestrel/tool').ToolResult} (a `tool`
@@ -2158,9 +2248,10 @@ export declare function attachUserImages(conversation: readonly Message[], paylo
2158
2248
  *
2159
2249
  * @example
2160
2250
  * ```ts
2161
- * // A denylist: deny the `delete` tool, allow everything else (default fallback).
2251
+ * // A denylist: deny the `delete` tool, allow everything else.
2162
2252
  * const authority = new Authority({
2163
2253
  * rules: [{ match: (c) => c.call.name === 'delete', zone: 'restricted', verdict: 'deny' }],
2254
+ * fallback: { zone: 'default', verdict: 'allow' },
2164
2255
  * })
2165
2256
  * authority.evaluate({ call: { id: '1', name: 'delete', arguments: {} } }) // { zone: 'restricted', verdict: 'deny' }
2166
2257
  * authority.evaluate({ call: { id: '2', name: 'add', arguments: {} } }) // { zone: 'default', verdict: 'allow' }
@@ -2168,7 +2259,7 @@ export declare function attachUserImages(conversation: readonly Message[], paylo
2168
2259
  */
2169
2260
  export declare class Authority implements AuthorityInterface {
2170
2261
  #private;
2171
- constructor(options?: AuthorityOptions);
2262
+ constructor(options: AuthorityOptions);
2172
2263
  evaluate(context: AuthorityContext): AuthorityDecision;
2173
2264
  ask(context: AuthorityContext, decision: AuthorityDecision, signal: AbortSignal): Promise<boolean>;
2174
2265
  }
@@ -2227,7 +2318,7 @@ export declare type AuthorityHandler = (context: AuthorityContext, decision: Aut
2227
2318
  export declare interface AuthorityInterface {
2228
2319
  /**
2229
2320
  * Evaluates one tool call against the ordered rules — returns the first matching rule's
2230
- * verdict, which allows when the rule names none, or the fallback when none match.
2321
+ * verdict, or the fallback when none match.
2231
2322
  *
2232
2323
  * @param context - The call under consideration (see {@link AuthorityContext})
2233
2324
  * @returns The first matching rule's verdict, or the fallback when none match
@@ -2256,16 +2347,14 @@ export declare interface AuthorityNote {
2256
2347
  *
2257
2348
  * @remarks
2258
2349
  * `rules` are evaluated in order, first match wins (see {@link AuthorityRule}).
2259
- * `fallback` is the {@link AuthorityDecision} returned when no rule matches.
2260
- * Default: `{ zone: DEFAULT_AUTHORITY_ZONE, verdict: 'allow' }` (allow-unmatched — a
2261
- * rules list of denials acts as a denylist). Set `fallback` to a `verdict: 'deny'`
2262
- * decision to flip the gate to deny-by-default (an allowlist — only matched rules
2263
- * that allow get through). `ask` is the {@link AuthorityHandler} that answers each `ask`
2264
- * verdict; absent, every ask is refused as unanswered.
2350
+ * `fallback` is the {@link AuthorityDecision} returned when no rule matches, and it is required:
2351
+ * a `verdict: 'deny'` fallback makes an allowlist (only matched rules that allow get through), and a
2352
+ * `verdict: 'allow'` fallback makes a denylist. `ask` is the {@link AuthorityHandler} that answers
2353
+ * each `ask` verdict; absent, every ask is refused as unanswered.
2265
2354
  */
2266
2355
  export declare interface AuthorityOptions {
2267
2356
  readonly rules?: readonly AuthorityRule[];
2268
- readonly fallback?: AuthorityDecision;
2357
+ readonly fallback: AuthorityDecision;
2269
2358
  readonly ask?: AuthorityHandler;
2270
2359
  }
2271
2360
 
@@ -2274,13 +2363,14 @@ export declare interface AuthorityOptions {
2274
2363
  *
2275
2364
  * @remarks
2276
2365
  * The first rule whose `match` returns true decides; if none match, the authority's
2277
- * `fallback` decides. A matched rule with no `verdict` allows. `zone` classifies the matched
2278
- * call; `reason` is the optional explanation carried into the {@link AuthorityDecision}.
2366
+ * `fallback` decides. `zone` classifies the matched call; `verdict` is required, and an
2367
+ * `Authority` refuses a rule with none at construction; `reason` is the optional explanation
2368
+ * carried into the {@link AuthorityDecision}.
2279
2369
  */
2280
2370
  export declare interface AuthorityRule {
2281
2371
  readonly match: (context: AuthorityContext) => boolean;
2282
2372
  readonly zone: string;
2283
- readonly verdict?: AuthorityVerdict;
2373
+ readonly verdict: AuthorityVerdict;
2284
2374
  readonly reason?: string;
2285
2375
  }
2286
2376
 
@@ -2740,7 +2830,7 @@ export declare class Classifier implements ClassifierInterface {
2740
2830
  * Asks the judge every question the filing still lacks, in the measured order.
2741
2831
  * @param requests - The request ids, which skip category questions and receive only enabled request-topic questions
2742
2832
  * @param signal - The caller's signal; an abort returns a fault with completed judgments and usage
2743
- * @returns The judgment keys, summed usage, and one attempt per logical question, in asking order; a throw from the assign or entities handler, a scheduler rejection, or a caller abort returns the partial result with `fault`; a judge rejection under a live signal leaves that question undecided and sets no `fault`
2833
+ * @returns The judgment keys, summed usage, and one attempt per logical question, in asking order; a throw from the assign or entities handler, a scheduler rejection, or a caller abort returns the partial result with `fault`; a judge rejection under a live signal leaves that question undecided and sets `failure`
2744
2834
  */
2745
2835
  classify(requests: ReadonlySet<string>, signal: AbortSignal): Promise<ClassifierResult>;
2746
2836
  /**
@@ -2805,7 +2895,7 @@ export declare interface ClassifierInterface {
2805
2895
  *
2806
2896
  * @param requests - The request ids, which skip category questions and receive only enabled request-topic questions
2807
2897
  * @param signal - The signal that aborts the questions; completed judgments stay recorded
2808
- * @returns The judgment keys, usage spent, and one attempt per logical question; a throw from the assign or entities handler, a scheduler rejection, or a caller abort returns the partial result with `fault`; a judge rejection under a live signal leaves that question undecided and sets no `fault`
2898
+ * @returns The judgment keys, usage spent, and one attempt per logical question; a throw from the assign or entities handler, a scheduler rejection, or a caller abort returns the partial result with `fault`; a judge rejection under a live signal leaves that question undecided and sets `failure`
2809
2899
  */
2810
2900
  classify(requests: ReadonlySet<string>, signal: AbortSignal): Promise<ClassifierResult>;
2811
2901
  /**
@@ -2861,6 +2951,8 @@ export declare interface ClassifierInterface {
2861
2951
  * no scheduler, the call takes no host turn and reads no added clock.
2862
2952
  */
2863
2953
  export declare interface ClassifierOptions {
2954
+ /** Sets what a refused question or a deterministic judge failure leaves behind. Default `true`: nothing, so the next call asks again. `false` holds the question, so no later call asks it. */
2955
+ readonly strict?: boolean;
2864
2956
  readonly conversation: ConversationInterface;
2865
2957
  readonly judge: JudgeInterface;
2866
2958
  readonly questions: LedgerQuestion;
@@ -2877,7 +2969,7 @@ export declare interface ClassifierOptions {
2877
2969
  *
2878
2970
  * @remarks
2879
2971
  * `cached` means the conversation already held a matching judgment, so the classifier did not call the judgment manager.
2880
- * `skipped` means the classifier held the question, after a deterministic failure or because a message it names left the conversation, and did not call the judgment manager.
2972
+ * `skipped` means the classifier held the question, after a deterministic failure under `strict: false` or because a message it names left the conversation, and did not call the judgment manager.
2881
2973
  * `resolved` means the judgment manager's resolve call fulfilled. `failed` means it rejected while the caller's signal was live.
2882
2974
  * `aborted` means it rejected with a `JudgeAbortError` or after the caller's signal aborted.
2883
2975
  */
@@ -2899,6 +2991,8 @@ export declare interface ClassifierResult {
2899
2991
  readonly attempts: readonly ClassifierAttempt[];
2900
2992
  /** Holds the error when an assign or entities handler throw, a scheduler rejection, or a caller abort interrupts classification; judgments and usage retain the partial result. A judge rejection under a live signal sets no fault. */
2901
2993
  readonly fault?: Error;
2994
+ /** Holds the first judge rejection of this call under a live signal: that question stays undecided and the filing goes on, so the result is whole but for it. A question held from an earlier call reports nothing. */
2995
+ readonly failure?: Error;
2902
2996
  }
2903
2997
 
2904
2998
  /**
@@ -3115,18 +3209,21 @@ export declare function computeThinking(message: Pick<Message, 'thinking' | 'con
3115
3209
 
3116
3210
  /**
3117
3211
  * Reports a context snapshot that `isMemoSnapshot` refuses, thrown by the construction of a
3118
- * {@link import('./memos/MemoManager.js').MemoManager} before it seats any state, carrying the
3119
- * machine-readable `code` `'SNAPSHOT'`.
3212
+ * {@link import('./memos/MemoManager.js').MemoManager} before it seats any state or by a memo store,
3213
+ * or image files a build has no user turn to carry, carrying the machine-readable `code`
3214
+ * `'SNAPSHOT' | 'IMAGES'`.
3120
3215
  *
3121
3216
  * @remarks
3122
3217
  * A `snapshot` option crosses a foreign boundary (a client, a store, a file), so the manager copies
3123
3218
  * it through JSON and checks the copy: a value JSON cannot carry, a revision missing a field, a
3124
3219
  * non-finite `time`, a sparse `memos` array, a non-string `id`, or a non-array `memos` is a
3125
- * programmer error and throws this with `'SNAPSHOT'`. Narrow a caught value with
3126
- * {@link isContextError} and branch on `error.code`.
3220
+ * programmer error and throws this with `'SNAPSHOT'`, its `context` holding the `faults`. A build
3221
+ * over a conversation that holds turns and no user turn, with image files in the active workspace,
3222
+ * throws `'IMAGES'` rather than dropping them. Narrow a caught value with {@link isContextError} and
3223
+ * branch on `error.code`.
3127
3224
  */
3128
3225
  export declare class ContextError extends Error {
3129
- /** Names the machine-readable condition — `'SNAPSHOT'`: a snapshot option that is not a memo snapshot. */
3226
+ /** Names the machine-readable condition — `'SNAPSHOT'`: a snapshot that is not a memo snapshot; `'IMAGES'`: image files with no user turn to carry them. */
3130
3227
  readonly code: ContextErrorCode;
3131
3228
  /** Holds the values that locate the failure, or `undefined` when none were supplied. */
3132
3229
  readonly context: Readonly<Record<string, unknown>> | undefined;
@@ -3146,7 +3243,7 @@ export declare class ContextError extends Error {
3146
3243
  * @remarks
3147
3244
  * `'SNAPSHOT'`: a `snapshot` option that `isMemoSnapshot` refuses after it is copied through JSON.
3148
3245
  */
3149
- export declare type ContextErrorCode = 'SNAPSHOT';
3246
+ export declare type ContextErrorCode = 'SNAPSHOT' | 'IMAGES';
3150
3247
 
3151
3248
  /**
3152
3249
  * Overrides one context section's format — an `open` / `render` / `close` trio
@@ -3305,12 +3402,12 @@ export declare const CONVERSATION_ROLES: readonly ["user", "assistant", "tool"];
3305
3402
 
3306
3403
  /**
3307
3404
  * Reports a conversation with no {@link ConversationSummaryHandler} to fold its messages with, a
3308
- * `sections` cap below `1`, a `keep` that is not a nonnegative safe integer, a summarizer digest
3405
+ * `sections` cap that is not a positive safe integer, a `keep` that is not a nonnegative safe integer, a summarizer digest
3309
3406
  * whose trimmed text is empty, a judgment or judge request that JSON cannot carry, a stored or
3310
3407
  * selected message whose role is not a conversation role, or a malformed snapshot — thrown by the
3311
3408
  * `compact()` and `add` methods of a {@link ConversationInterface}, its construction, or its
3312
3409
  * judgment store, or returned as the `fault` of an agent selection, carrying the machine-readable
3313
- * `code` `'SUMMARIZER' | 'SECTIONS' | 'JUDGMENT' | 'KEEP' | 'SUMMARY' | 'ROLE' | 'SNAPSHOT'`.
3410
+ * `code` `'SUMMARIZER' | 'SECTIONS' | 'JUDGMENT' | 'KEEP' | 'SUMMARY' | 'ROLE' | 'MESSAGE' | 'SNAPSHOT' | 'ID'`.
3314
3411
  *
3315
3412
  * @remarks
3316
3413
  * Compaction requires a summarizer (it digests the folded slice into a section summary); a
@@ -3318,7 +3415,7 @@ export declare const CONVERSATION_ROLES: readonly ["user", "assistant", "tool"];
3318
3415
  * is a programmer error and throws this with `'SUMMARIZER'`.
3319
3416
  * A `sections` cap (on {@link import('./types.js').ConversationOptions} /
3320
3417
  * {@link import('./types.js').ConversationManagerOptions} /
3321
- * {@link import('./types.js').CompactOptions}) must be `>= 1`, and cannot combine with
3418
+ * {@link import('./types.js').CompactOptions}) must be a positive safe integer, and cannot combine with
3322
3419
  * `cumulative` — either is a programmer error and throws this with `'SECTIONS'`. A `keep` on the same options must be a nonnegative
3323
3420
  * safe integer — any other value is a programmer error and throws this with `'KEEP'`. A judgment
3324
3421
  * record or a judge request that JSON cannot carry, or whose copy fails its guard, is a
@@ -3326,13 +3423,16 @@ export declare const CONVERSATION_ROLES: readonly ["user", "assistant", "tool"];
3326
3423
  * where one exists. A summarizer digest whose trimmed text is empty rejects the `compact()` with
3327
3424
  * `'SUMMARY'`. A stored message plays a `ConversationRole`: `add` refuses any other role with
3328
3425
  * `'ROLE'` before it stores any message of the batch, a hydrating snapshot that holds one throws
3329
- * `'ROLE'`, and an agent's selection that holds one becomes a `'ROLE'` fault. A hydrating snapshot
3330
- * that fails `isConversationSnapshot` or repeats an id throws `'SNAPSHOT'`; a judgment the guard
3331
- * admits but JSON cannot carry still throws `'JUDGMENT'`. Narrow a caught value with
3426
+ * `'ROLE'`, and an agent's selection that holds one becomes a `'ROLE'` fault. `add` refuses an input
3427
+ * whose other members fail `isMessageInput` with `'MESSAGE'`, its `context` holding the `faults`,
3428
+ * before it stores any message of the batch. A hydrating snapshot that fails
3429
+ * `isConversationSnapshot` or repeats an id, and a store row or written snapshot that does, throw
3430
+ * `'SNAPSHOT'`; a judgment the guard admits but JSON cannot carry still throws `'JUDGMENT'`. A
3431
+ * manager's `add` of an id it already holds throws `'ID'`. Narrow a caught value with
3332
3432
  * {@link isConversationError} and branch on `error.code`.
3333
3433
  */
3334
3434
  export declare class ConversationError extends Error {
3335
- /** Names the machine-readable condition — `'SUMMARIZER'`: a `compact()` with no summarizer; `'SECTIONS'`: a sub-1 `sections` cap, or a cap combined with `cumulative`; `'JUDGMENT'`: a judgment or judge request that is not JSON; `'KEEP'`: a `keep` that is not a nonnegative safe integer; `'SUMMARY'`: a summarizer digest whose trimmed text is empty; `'ROLE'`: a stored or selected message whose role is not a `ConversationRole`; `'SNAPSHOT'`: a snapshot that fails `isConversationSnapshot` or repeats an id. */
3435
+ /** Names the machine-readable condition — `'SUMMARIZER'`: a `compact()` with no summarizer; `'SECTIONS'`: a `sections` cap that is not a positive safe integer, or a cap combined with `cumulative`; `'JUDGMENT'`: a judgment or judge request that is not JSON; `'KEEP'`: a `keep` that is not a nonnegative safe integer; `'SUMMARY'`: a summarizer digest whose trimmed text is empty; `'ROLE'`: a stored or selected message whose role is not a `ConversationRole`; `'MESSAGE'`: a message input whose other members fail `isMessageInput`; `'SNAPSHOT'`: a snapshot that fails `isConversationSnapshot` or repeats an id; `'ID'`: a manager's `add` of an id it already holds. */
3336
3436
  readonly code: ConversationErrorCode;
3337
3437
  /** Holds the values that locate the failure, such as the `question` id of a malformed question, or `undefined` when none were supplied. */
3338
3438
  readonly context: Readonly<Record<string, unknown>> | undefined;
@@ -3359,7 +3459,7 @@ export declare class ConversationError extends Error {
3359
3459
  * `'SNAPSHOT'`: a snapshot that fails `isConversationSnapshot` or repeats an id; a judgment the
3360
3460
  * guard admits but JSON cannot carry still raises `'JUDGMENT'`.
3361
3461
  */
3362
- export declare type ConversationErrorCode = 'SUMMARIZER' | 'SECTIONS' | 'JUDGMENT' | 'KEEP' | 'SUMMARY' | 'ROLE' | 'SNAPSHOT';
3462
+ export declare type ConversationErrorCode = 'SUMMARIZER' | 'SECTIONS' | 'JUDGMENT' | 'KEEP' | 'SUMMARY' | 'ROLE' | 'MESSAGE' | 'SNAPSHOT' | 'ID';
3363
3463
 
3364
3464
  /**
3365
3465
  * Maps the push observation surface of a {@link ConversationInterface} — the compaction
@@ -3678,7 +3778,8 @@ export declare interface ConversationInterface {
3678
3778
  * - **Registry.** Conversations live in an insertion-ordered `Map` keyed by `id`. `add(input?)`
3679
3779
  * mints a {@link Conversation} (its `id` from `input` or `crypto.randomUUID()`), flowing the
3680
3780
  * default `#summarize` / `#keep` of the manager in unless the `input` overrides them, and stores
3681
- * it (an already-present `id` overwrites — last write wins). `count` is the map size,
3781
+ * it (an already-present `id` throws a `ConversationError` coded `'ID'`, because replacing a live
3782
+ * conversation would orphan its turns). `count` is the map size,
3682
3783
  * `conversation(id)` looks one up, `conversations()` lists them in insertion order.
3683
3784
  * - **Active pointer.** `active` is the active conversation (the conversation an agent run binds
3684
3785
  * when it names none), `undefined` until the first `add` (which auto-activates it — a registry
@@ -3728,7 +3829,7 @@ export declare class ConversationManager implements ConversationManagerInterface
3728
3829
  * - **Registry.** `count` is how many are stored. `add(input?)` mints a
3729
3830
  * {@link ConversationInterface} (its `id` from `input` or a random UUID), flowing the
3730
3831
  * default `summarize` / `keep` of the manager in unless the `input` overrides them; `add` of an
3731
- * already-present `id` overwrites it (last write wins). `conversation(id)` looks one up
3832
+ * already-present `id` throws (code `'ID'`). `conversation(id)` looks one up
3732
3833
  * (`undefined` when absent); `conversations()` lists them in insertion order.
3733
3834
  * - **Active pointer.** `active` is the active conversation (the conversation an agent run binds
3734
3835
  * when it names none, and the one the context renders with no selection), `undefined` until the
@@ -3770,11 +3871,11 @@ export declare interface ConversationManagerInterface {
3770
3871
  /**
3771
3872
  * Mints a conversation, taking its `id` from the input or a fresh UUID and flowing the
3772
3873
  * default `summarize` / `keep` of the manager in unless the input overrides them —
3773
- * auto-activates the first, and an already-present `id` overwrites, last write wins.
3874
+ * auto-activates the first, and an already-present `id` throws.
3774
3875
  *
3775
3876
  * @param input - Optional {@link ConversationInput} overrides
3776
3877
  * @returns The created conversation
3777
- * @throws ConversationError Thrown when `snapshot` is malformed or repeats an id (code `'SNAPSHOT'`) or holds a message whose role is not a `ConversationRole` (code `'ROLE'`); nothing registers and `active` is unchanged
3878
+ * @throws ConversationError Thrown when the `id` is already live (code `'ID'`), or when `snapshot` is malformed or repeats an id (code `'SNAPSHOT'`) or holds a message whose role is not a `ConversationRole` (code `'ROLE'`); nothing registers and `active` is unchanged
3778
3879
  */
3779
3880
  add(input?: ConversationInput): ConversationInterface;
3780
3881
  /**
@@ -3977,8 +4078,8 @@ export declare type ConversationRole = (typeof CONVERSATION_ROLES)[number];
3977
4078
  * {@link ConversationManagerInterface} hydrates a conversation from it through that seam (see
3978
4079
  * {@link ConversationManagerInterface.open}). It is narrowed back from an untrusted storage read by
3979
4080
  * {@link import('./validators.js').isConversationSnapshot} (the total boundary guard), which
3980
- * admits unknown members: a 0.0.29 snapshot that carries a conversation `summary` passes and
3981
- * hydrates without it.
4081
+ * is exact: an unknown member refuses, so a 0.0.29 snapshot that carries a conversation `summary`
4082
+ * throws until its row is rewritten without the key.
3982
4083
  */
3983
4084
  export declare interface ConversationSnapshot {
3984
4085
  readonly id: string;
@@ -3990,6 +4091,158 @@ export declare interface ConversationSnapshot {
3990
4091
  readonly messages: readonly Message[];
3991
4092
  }
3992
4093
 
4094
+ /** Reads the faults of a refused conversation snapshot. */
4095
+ export declare const conversationSnapshotContract: ContractInterface<Readonly<{
4096
+ id: string;
4097
+ sections: readonly Readonly<{
4098
+ id: string;
4099
+ summary: string;
4100
+ messages: readonly Readonly<{
4101
+ id: string;
4102
+ role: "assistant" | "system" | "tool" | "user";
4103
+ content: string;
4104
+ } & {
4105
+ calls?: readonly Readonly<{
4106
+ id: string;
4107
+ name: string;
4108
+ arguments: {
4109
+ readonly [k: string]: JSONValue;
4110
+ };
4111
+ } & {}>[];
4112
+ call?: string;
4113
+ images?: readonly string[];
4114
+ thinking?: string;
4115
+ }>[];
4116
+ } & {}>[];
4117
+ messages: readonly Readonly<{
4118
+ id: string;
4119
+ role: "assistant" | "system" | "tool" | "user";
4120
+ content: string;
4121
+ } & {
4122
+ calls?: readonly Readonly<{
4123
+ id: string;
4124
+ name: string;
4125
+ arguments: {
4126
+ readonly [k: string]: JSONValue;
4127
+ };
4128
+ } & {}>[];
4129
+ call?: string;
4130
+ images?: readonly string[];
4131
+ thinking?: string;
4132
+ }>[];
4133
+ } & {
4134
+ judgments?: readonly (Readonly<{
4135
+ id: string;
4136
+ question: Readonly<{
4137
+ form: "choice";
4138
+ criteria: {
4139
+ readonly [k: string]: string | readonly JSONValue[] | {
4140
+ readonly [k: string]: JSONValue;
4141
+ } | null;
4142
+ };
4143
+ } & {
4144
+ instructions?: string | readonly JSONValue[] | {
4145
+ readonly [k: string]: JSONValue;
4146
+ };
4147
+ }> | Readonly<{
4148
+ form: "score";
4149
+ criteria: readonly (string | readonly JSONValue[] | {
4150
+ readonly [k: string]: JSONValue;
4151
+ } | null)[];
4152
+ } & {
4153
+ instructions?: string | readonly JSONValue[] | {
4154
+ readonly [k: string]: JSONValue;
4155
+ };
4156
+ }> | Readonly<{
4157
+ form: "noul";
4158
+ } & {
4159
+ instructions?: string | readonly JSONValue[] | {
4160
+ readonly [k: string]: JSONValue;
4161
+ };
4162
+ criteria?: Readonly<{} & {
4163
+ true?: string | readonly JSONValue[] | {
4164
+ readonly [k: string]: JSONValue;
4165
+ };
4166
+ false?: string | readonly JSONValue[] | {
4167
+ readonly [k: string]: JSONValue;
4168
+ };
4169
+ }>;
4170
+ }>;
4171
+ model: string;
4172
+ sources: readonly string[];
4173
+ state: string;
4174
+ time: number;
4175
+ answer: Readonly<{
4176
+ form: "choice";
4177
+ probabilities: {
4178
+ readonly [k: string]: number;
4179
+ };
4180
+ } & {}> | Readonly<{
4181
+ form: "score";
4182
+ probabilities: readonly number[];
4183
+ } & {}> | Readonly<{
4184
+ form: "noul";
4185
+ noul: number;
4186
+ } & {}>;
4187
+ } & {
4188
+ usage?: Readonly<{
4189
+ prompt: number;
4190
+ completion: number;
4191
+ total: number;
4192
+ } & {}>;
4193
+ }> | Readonly<{
4194
+ id: string;
4195
+ question: Readonly<{
4196
+ form: "choice";
4197
+ criteria: {
4198
+ readonly [k: string]: string | readonly JSONValue[] | {
4199
+ readonly [k: string]: JSONValue;
4200
+ } | null;
4201
+ };
4202
+ } & {
4203
+ instructions?: string | readonly JSONValue[] | {
4204
+ readonly [k: string]: JSONValue;
4205
+ };
4206
+ }> | Readonly<{
4207
+ form: "score";
4208
+ criteria: readonly (string | readonly JSONValue[] | {
4209
+ readonly [k: string]: JSONValue;
4210
+ } | null)[];
4211
+ } & {
4212
+ instructions?: string | readonly JSONValue[] | {
4213
+ readonly [k: string]: JSONValue;
4214
+ };
4215
+ }> | Readonly<{
4216
+ form: "noul";
4217
+ } & {
4218
+ instructions?: string | readonly JSONValue[] | {
4219
+ readonly [k: string]: JSONValue;
4220
+ };
4221
+ criteria?: Readonly<{} & {
4222
+ true?: string | readonly JSONValue[] | {
4223
+ readonly [k: string]: JSONValue;
4224
+ };
4225
+ false?: string | readonly JSONValue[] | {
4226
+ readonly [k: string]: JSONValue;
4227
+ };
4228
+ }>;
4229
+ }>;
4230
+ model: string;
4231
+ sources: readonly string[];
4232
+ state: string;
4233
+ time: number;
4234
+ refusal: Readonly<{
4235
+ missing: readonly string[];
4236
+ } & {}>;
4237
+ } & {
4238
+ usage?: Readonly<{
4239
+ prompt: number;
4240
+ completion: number;
4241
+ total: number;
4242
+ } & {}>;
4243
+ }>)[];
4244
+ }>>;
4245
+
3993
4246
  /**
3994
4247
  * Represents one row of the table a {@link
3995
4248
  * import('./stores/DatabaseConversationStore.js').DatabaseConversationStore} persists
@@ -4014,6 +4267,116 @@ export declare interface ConversationSnapshotRow {
4014
4267
  readonly snapshot: unknown;
4015
4268
  }
4016
4269
 
4270
+ /**
4271
+ * Describes a conversation snapshot exactly: an unknown key refuses, so a key a later version adds never
4272
+ * reads as absent.
4273
+ *
4274
+ * @remarks
4275
+ * `isConversationSnapshot` is the door a hydrate and a store read, and this shape fills a refusal's
4276
+ * faults. A lockstep test holds that `is` implies the guard, and on the snapshot fixtures the converse.
4277
+ */
4278
+ export declare const conversationSnapshotShape: ObjectShape< {
4279
+ id: StringShape;
4280
+ sections: ArrayShape<ObjectShape< {
4281
+ id: StringShape;
4282
+ summary: StringShape;
4283
+ messages: ArrayShape<ObjectShape< {
4284
+ id: StringShape;
4285
+ role: LiteralShape<readonly ["system", "user", "assistant", "tool"]>;
4286
+ content: StringShape;
4287
+ calls: OptionalShape<ArrayShape<ObjectShape< {
4288
+ id: StringShape;
4289
+ name: StringShape;
4290
+ arguments: ObjectShape<Record<never, never>, JSONShape>;
4291
+ }, boolean | ContractShape>>>;
4292
+ call: OptionalShape<StringShape>;
4293
+ images: OptionalShape<ArrayShape<StringShape>>;
4294
+ thinking: OptionalShape<StringShape>;
4295
+ }, boolean | ContractShape>>;
4296
+ }, boolean | ContractShape>>;
4297
+ messages: ArrayShape<ObjectShape< {
4298
+ id: StringShape;
4299
+ role: LiteralShape<readonly ["system", "user", "assistant", "tool"]>;
4300
+ content: StringShape;
4301
+ calls: OptionalShape<ArrayShape<ObjectShape< {
4302
+ id: StringShape;
4303
+ name: StringShape;
4304
+ arguments: ObjectShape<Record<never, never>, JSONShape>;
4305
+ }, boolean | ContractShape>>>;
4306
+ call: OptionalShape<StringShape>;
4307
+ images: OptionalShape<ArrayShape<StringShape>>;
4308
+ thinking: OptionalShape<StringShape>;
4309
+ }, boolean | ContractShape>>;
4310
+ judgments: OptionalShape<ArrayShape<UnionShape<readonly [ObjectShape< {
4311
+ id: StringShape;
4312
+ question: UnionShape<readonly [ObjectShape< {
4313
+ form: LiteralShape<readonly ["choice"]>;
4314
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
4315
+ criteria: ObjectShape<Record<never, never>, NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
4316
+ }, boolean | ContractShape>, ObjectShape< {
4317
+ form: LiteralShape<readonly ["score"]>;
4318
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
4319
+ criteria: ArrayShape<NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
4320
+ }, boolean | ContractShape>, ObjectShape< {
4321
+ form: LiteralShape<readonly ["noul"]>;
4322
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
4323
+ criteria: OptionalShape<ObjectShape< {
4324
+ true: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
4325
+ false: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
4326
+ }, boolean | ContractShape>>;
4327
+ }, boolean | ContractShape>]>;
4328
+ model: StringShape;
4329
+ sources: ArrayShape<StringShape>;
4330
+ state: StringShape;
4331
+ time: NumberShape;
4332
+ usage: OptionalShape<ObjectShape< {
4333
+ prompt: NumberShape;
4334
+ completion: NumberShape;
4335
+ total: NumberShape;
4336
+ }, boolean | ContractShape>>;
4337
+ answer: UnionShape<readonly [ObjectShape< {
4338
+ form: LiteralShape<readonly ["choice"]>;
4339
+ probabilities: ObjectShape<Record<never, never>, NumberShape>;
4340
+ }, boolean | ContractShape>, ObjectShape< {
4341
+ form: LiteralShape<readonly ["score"]>;
4342
+ probabilities: ArrayShape<NumberShape>;
4343
+ }, boolean | ContractShape>, ObjectShape< {
4344
+ form: LiteralShape<readonly ["noul"]>;
4345
+ noul: NumberShape;
4346
+ }, boolean | ContractShape>]>;
4347
+ }, boolean | ContractShape>, ObjectShape< {
4348
+ id: StringShape;
4349
+ question: UnionShape<readonly [ObjectShape< {
4350
+ form: LiteralShape<readonly ["choice"]>;
4351
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
4352
+ criteria: ObjectShape<Record<never, never>, NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
4353
+ }, boolean | ContractShape>, ObjectShape< {
4354
+ form: LiteralShape<readonly ["score"]>;
4355
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
4356
+ criteria: ArrayShape<NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
4357
+ }, boolean | ContractShape>, ObjectShape< {
4358
+ form: LiteralShape<readonly ["noul"]>;
4359
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
4360
+ criteria: OptionalShape<ObjectShape< {
4361
+ true: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
4362
+ false: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
4363
+ }, boolean | ContractShape>>;
4364
+ }, boolean | ContractShape>]>;
4365
+ model: StringShape;
4366
+ sources: ArrayShape<StringShape>;
4367
+ state: StringShape;
4368
+ time: NumberShape;
4369
+ usage: OptionalShape<ObjectShape< {
4370
+ prompt: NumberShape;
4371
+ completion: NumberShape;
4372
+ total: NumberShape;
4373
+ }, boolean | ContractShape>>;
4374
+ refusal: ObjectShape< {
4375
+ missing: ArrayShape<StringShape>;
4376
+ }, boolean | ContractShape>;
4377
+ }, boolean | ContractShape>]>>>;
4378
+ }, boolean | ContractShape>;
4379
+
4017
4380
  /**
4018
4381
  * Persists a {@link ConversationSnapshot} durably — the async `get` / `set` / `delete` primitives,
4019
4382
  * keyed by a conversation id and holding no expiry, the exact analogue of {@link
@@ -4251,16 +4614,29 @@ export declare function createAgentQueue(options: AgentQueueOptions): QueueInter
4251
4614
  *
4252
4615
  * @example
4253
4616
  * ```ts
4254
- * import { createAgentRegistry } from '@orkestrel/agent'
4617
+ * import { createAgentRegistry, createAuthority } from '@orkestrel/agent'
4255
4618
  * import type { ProviderInterface } from '@orkestrel/agent'
4619
+ * import { numberShape, objectShape } from '@orkestrel/contract'
4256
4620
  * import { createTool } from '@orkestrel/tool'
4257
4621
  *
4258
4622
  * declare const provider: ProviderInterface // any concrete implementation supplied by the host app
4259
4623
  * const registry = createAgentRegistry({
4260
4624
  * providers: { main: provider },
4261
- * tools: { add: createTool({ name: 'add', execute: (a) => Number(a.x) + Number(a.y) }) },
4625
+ * tools: {
4626
+ * add: createTool({
4627
+ * name: 'add',
4628
+ * contract: objectShape({ x: numberShape(), y: numberShape() }),
4629
+ * execute: (a) => Number(a.x) + Number(a.y),
4630
+ * }),
4631
+ * },
4632
+ * authorities: { open: createAuthority({ fallback: { zone: 'default', verdict: 'allow' } }) },
4633
+ * })
4634
+ * const agent = registry.build({
4635
+ * provider: 'main',
4636
+ * messages: [{ role: 'user', content: 'Hi.' }],
4637
+ * tools: ['add'],
4638
+ * authority: 'open',
4262
4639
  * })
4263
- * const agent = registry.build({ provider: 'main', messages: [{ role: 'user', content: 'Hi.' }] })
4264
4640
  * ```
4265
4641
  */
4266
4642
  export declare function createAgentRegistry(options: AgentRegistryOptions): AgentRegistryInterface;
@@ -4319,7 +4695,11 @@ export declare function createAgentRunner(options: AgentRunnerOptions): RunnerIn
4319
4695
  * @example
4320
4696
  * ```ts
4321
4697
  * const approver = createApprover()
4322
- * const authority = createAuthority({ rules, ask: approver.ask })
4698
+ * const authority = createAuthority({
4699
+ * rules,
4700
+ * fallback: { zone: 'default', verdict: 'deny' },
4701
+ * ask: approver.ask,
4702
+ * })
4323
4703
  * const agent = createAgent(provider, { tools, authority })
4324
4704
  * const stream = agent.stream({ prompt: { content: 'Tidy the notes.' } })
4325
4705
  * for await (const frame of agentStreamToFrames(stream, approver)) {
@@ -4332,20 +4712,20 @@ export declare function createApprover(): ApproverInterface;
4332
4712
  /**
4333
4713
  * Creates a policy gate — an {@link AuthorityInterface} the agent loop consults before
4334
4714
  * each tool call runs, evaluating the ordered rules first-match-wins and falling back
4335
- * to the configured default when none match.
4715
+ * to the required `fallback` when none match.
4336
4716
  *
4337
4717
  * @remarks
4338
- * `rules` are evaluated in order — the first whose `match` is true decides (a matched
4339
- * rule with no `verdict` allows). When no rule matches, the `fallback` decides. Default:
4340
- * `{ zone: DEFAULT_AUTHORITY_ZONE, verdict: 'allow' }` (allow-unmatched — a rules list of
4341
- * denials acts as a denylist). Pass a `verdict: 'deny'` `fallback` to flip the gate to
4342
- * deny-by-default (an allowlist). `ask` answers each `ask` verdict; with none, every ask is
4343
- * refused as unanswered. Wire the result into `createAgent` through `AgentOptions.authority`:
4344
- * a denied call is fed back to the model as a denial `ToolResult` (not executed), so the model
4345
- * can react. Synchronous — `evaluate` returns the verdict directly; only `ask` is async.
4718
+ * `rules` are evaluated in order — the first whose `match` is true decides, and each rule names its
4719
+ * `verdict`. When no rule matches, the `fallback` decides: a `verdict: 'deny'` fallback makes an
4720
+ * allowlist, and a `verdict: 'allow'` fallback makes a denylist. `ask` answers each `ask` verdict;
4721
+ * with none, every ask is refused as unanswered. Wire the result into `createAgent` through
4722
+ * `AgentOptions.authority`: a denied call is fed back to the model as a denial `ToolResult` (not
4723
+ * executed), so the model can react. Synchronous — `evaluate` returns the verdict directly; only
4724
+ * `ask` is async.
4346
4725
  *
4347
- * @param options - Optional `rules` (ordered), `fallback`, and `ask` (see {@link AuthorityOptions})
4726
+ * @param options - The `fallback`, and optional `rules` (ordered) and `ask` (see {@link AuthorityOptions})
4348
4727
  * @returns A working {@link AuthorityInterface}
4728
+ * @throws {AgentError} Thrown when the `fallback` is missing or malformed, or a rule has no valid `verdict` (code `'AUTHORITY'`)
4349
4729
  *
4350
4730
  * @example
4351
4731
  * ```ts
@@ -4354,11 +4734,12 @@ export declare function createApprover(): ApproverInterface;
4354
4734
  * // Deny the `delete` tool, allow everything else.
4355
4735
  * const authority = createAuthority({
4356
4736
  * rules: [{ match: (c) => c.call.name === 'delete', zone: 'restricted', verdict: 'deny' }],
4737
+ * fallback: { zone: 'default', verdict: 'allow' },
4357
4738
  * })
4358
4739
  * const agent = createAgent(provider, { tools, authority })
4359
4740
  * ```
4360
4741
  */
4361
- export declare function createAuthority(options?: AuthorityOptions): AuthorityInterface;
4742
+ export declare function createAuthority(options: AuthorityOptions): AuthorityInterface;
4362
4743
 
4363
4744
  /**
4364
4745
  * Creates an empty unbounded async channel — a {@link ChannelInterface} a producer writes
@@ -4456,7 +4837,7 @@ export declare function createConversation(options?: ConversationOptions): Conve
4456
4837
  * @remarks
4457
4838
  * Starts empty; `add(input?)` mints a {@link ConversationInterface} (its `id` from the input
4458
4839
  * or a random UUID), flowing the manager's default `summarize` / `keep` in unless the input
4459
- * overrides them, and stores it (an already-present `id` overwrites — last write wins) — and
4840
+ * overrides them, and stores it (an already-present `id` throws, code `'ID'`) — and
4460
4841
  * auto-activates the first one (a registry with conversations always has one `active`); a later
4461
4842
  * `add` leaves `active` unchanged. `switch(id)` re-points `active` (an unknown `id` returns
4462
4843
  * `undefined`, leaving `active` unchanged — lenient, never throws); `conversation(id)` /
@@ -4946,8 +5327,9 @@ export declare function cutListing(entries: readonly string[], room: number): st
4946
5327
  * the row `{ id: snapshot.id, snapshot }`.
4947
5328
  * - **`get(id)` resolves the stored snapshot for an id**, narrowing the opaque JSON column back to
4948
5329
  * a {@link ConversationSnapshot} ({@link import('../validators.js').isConversationSnapshot} — the
4949
- * total guard for an untrusted storage read), or `undefined` if none is stored, the blob is
4950
- * malformed, or the blob's own `id` is not the requested one.
5330
+ * total guard for an untrusted storage read), or `undefined` only when no row is stored. A row whose
5331
+ * blob is malformed or names another id throws a `ConversationError` coded `'SNAPSHOT'`, so `open`
5332
+ * and `create` stop rather than overwrite it, and `delete` still removes it.
4951
5333
  * - **`delete(id)` drops a snapshot by id**; an absent id is a no-op (no throw).
4952
5334
  *
4953
5335
  * Unlike a session store there is no idle-TTL / eviction — a persisted conversation lives until an
@@ -4984,12 +5366,12 @@ export declare class DatabaseConversationStore implements ConversationStoreInter
4984
5366
  *
4985
5367
  * @remarks
4986
5368
  * The column is an untrusted storage read, so a blob that fails
4987
- * {@link import('../validators.js').isConversationSnapshot}, or whose own `id` is not `id`,
4988
- * resolves `undefined` rather than a conversation under the wrong key.
5369
+ * {@link import('../validators.js').isConversationSnapshot}, or whose own `id` is not `id`, throws
5370
+ * rather than reading as absent, which would let a later `set` overwrite it.
4989
5371
  *
4990
5372
  * @param id - The conversation id to resolve (the row key)
4991
- * @returns The persisted snapshot, or `undefined` when no row is stored, the blob is malformed,
4992
- * or the blob names another id
5373
+ * @returns The persisted snapshot, or `undefined` when no row is stored
5374
+ * @throws {ConversationError} Thrown when the row's blob is malformed or names another id (code `'SNAPSHOT'`), with the faults under `context.faults`
4993
5375
  */
4994
5376
  get(id: string): Promise<ConversationSnapshot | undefined>;
4995
5377
  /**
@@ -4998,6 +5380,7 @@ export declare class DatabaseConversationStore implements ConversationStoreInter
4998
5380
  *
4999
5381
  * @param snapshot - The snapshot to store, keyed by its `id`
5000
5382
  * @returns A promise that resolves after the row is written
5383
+ * @throws {ConversationError} Thrown before any write when the snapshot fails the guard `get` reads (code `'SNAPSHOT'`), so no row is written that `get` refuses
5001
5384
  */
5002
5385
  set(snapshot: ConversationSnapshot): Promise<void>;
5003
5386
  /**
@@ -5031,8 +5414,9 @@ export declare class DatabaseConversationStore implements ConversationStoreInter
5031
5414
  * the row `{ id: snapshot.id, snapshot }`.
5032
5415
  * - **`get(id)` resolves the stored snapshot for an id**, narrowing the opaque JSON column back to
5033
5416
  * a {@link MemoSnapshot} ({@link import('../validators.js').isMemoSnapshot} — the total guard for
5034
- * an untrusted storage read), or `undefined` if none is stored, the blob is malformed, or the
5035
- * blob's own `id` is not the requested one.
5417
+ * an untrusted storage read), or `undefined` only when no row is stored. A row whose blob is malformed
5418
+ * or names another id throws a `ContextError` coded `'SNAPSHOT'`, so a host never overwrites it
5419
+ * unawares, and `delete` still removes it.
5036
5420
  * - **`delete(id)` drops a snapshot by id**; an absent id is a no-op (no throw).
5037
5421
  *
5038
5422
  * @example
@@ -5063,12 +5447,12 @@ export declare class DatabaseMemoStore implements MemoStoreInterface {
5063
5447
  *
5064
5448
  * @remarks
5065
5449
  * The column is an untrusted storage read, so a blob that fails
5066
- * {@link import('../validators.js').isMemoSnapshot}, or whose own `id` is not `id`, resolves
5067
- * `undefined` rather than a memo set under the wrong key.
5450
+ * {@link import('../validators.js').isMemoSnapshot}, or whose own `id` is not `id`, throws rather
5451
+ * than reading as absent.
5068
5452
  *
5069
5453
  * @param id - The memo set id to resolve (the row key)
5070
- * @returns The stored snapshot, or `undefined` when no row is stored, the blob is malformed, or
5071
- * the blob names another id
5454
+ * @returns The stored snapshot, or `undefined` when no row is stored
5455
+ * @throws {ContextError} Thrown when the row's blob is malformed or names another id (code `'SNAPSHOT'`), with the faults under `context.faults`
5072
5456
  */
5073
5457
  get(id: string): Promise<MemoSnapshot | undefined>;
5074
5458
  /**
@@ -5077,6 +5461,7 @@ export declare class DatabaseMemoStore implements MemoStoreInterface {
5077
5461
  *
5078
5462
  * @param snapshot - The snapshot to store, keyed by its `id`
5079
5463
  * @returns A promise that resolves after the row is written
5464
+ * @throws {ContextError} Thrown before any write when the snapshot fails the guard `get` reads (code `'SNAPSHOT'`), so no row is written that `get` refuses
5080
5465
  */
5081
5466
  set(snapshot: MemoSnapshot): Promise<void>;
5082
5467
  /**
@@ -5098,11 +5483,6 @@ export declare const DECISIVE_CATEGORIES: readonly LedgerCategory[];
5098
5483
  */
5099
5484
  export declare const DEFAULT_AGENT_LIMIT = 10;
5100
5485
 
5101
- /**
5102
- * Names the default zone for an unmatched tool call allowed by an authority.
5103
- */
5104
- export declare const DEFAULT_AUTHORITY_ZONE = "default";
5105
-
5106
5486
  /**
5107
5487
  * Sets the default number of recent live messages the `compact()` method of a
5108
5488
  * {@link ConversationInterface} retains verbatim — `0`, so a manual `compact()` keeps no recent tail and folds every
@@ -5165,6 +5545,25 @@ export declare const DEFAULT_RELAY_LIMIT = 1048576;
5165
5545
  */
5166
5546
  export declare function denyCall(call: ToolCall, reason: string | undefined): ToolResult;
5167
5547
 
5548
+ /**
5549
+ * Describes why a judge question refuses, in the text both of its doors throw.
5550
+ *
5551
+ * @remarks
5552
+ * The rule travels in the text because the question shape cannot state it: a record has no minimum
5553
+ * size, so a single-option choice refuses at the guard with no fault for the list to name.
5554
+ *
5555
+ * @param id - The question's id
5556
+ * @param faults - What the question shape's audit found
5557
+ * @param schema - The question shape's JSON Schema
5558
+ * @returns The refusal text, with the fault list on the lines after it
5559
+ * @example
5560
+ * ```ts
5561
+ * describeQuestionRefusal('team', [], judgeQuestionContract.schema)
5562
+ * // 'question team is malformed; a choice names two or more criteria, a score two or more levels, and a noul only true and false'
5563
+ * ```
5564
+ */
5565
+ export declare function describeQuestionRefusal(id: string, faults: readonly AuditFault[], schema: JSONSchema): string;
5566
+
5168
5567
  /**
5169
5568
  * Describes one relay refusal as the line its `422` response body carries.
5170
5569
  *
@@ -5186,6 +5585,26 @@ export declare function denyCall(call: ToolCall, reason: string | undefined): To
5186
5585
  */
5187
5586
  export declare function describeRelayRefusal(refusal: RelayRefusal): string;
5188
5587
 
5588
+ /**
5589
+ * Describes a snapshot a store refuses, naming its id, the first fault, and what a host does about it.
5590
+ *
5591
+ * @remarks
5592
+ * A store's row is the host's table, so the text tells the host to read the row itself and rewrite it,
5593
+ * or to delete it, rather than reading a refused row as absent, which would let `open` overwrite it.
5594
+ * The id and each fault segment are JSON-encoded and length-capped.
5595
+ *
5596
+ * @param noun - What the snapshot holds, such as `conversation`
5597
+ * @param id - The id the row is keyed by
5598
+ * @param faults - The faults of the snapshot's shape
5599
+ * @returns The refusal's text
5600
+ * @example
5601
+ * ```ts
5602
+ * describeSnapshotRefusal('conversation', 'c1', [{ reason: 'extra', path: ['summary'] }])
5603
+ * // 'conversation "c1" holds a snapshot this version refuses (extra key "summary" at the root; ...'
5604
+ * ```
5605
+ */
5606
+ export declare function describeSnapshotRefusal(noun: string, id: unknown, faults: readonly AuditFault[]): string;
5607
+
5189
5608
  /** Matches the logprob decoding failure `invalid or duplicate top logprob token`, which the ledger holds for the ledger's life. */
5190
5609
  export declare const DETERMINISTIC_JUDGE_ERROR: RegExp;
5191
5610
 
@@ -5249,8 +5668,8 @@ export declare function estimateRequest(request: ProviderRequest): number;
5249
5668
 
5250
5669
  /**
5251
5670
  * Estimates the context-token footprint of a string — the deterministic `ceil(length / 4)`
5252
- * character heuristic {@link estimateMessages} sums over a conversation's messages (the default
5253
- * context-budget estimator).
5671
+ * character heuristic {@link import('./agents/helpers.js').estimateMessages} sums over a conversation's
5672
+ * messages (the default context-budget estimator).
5254
5673
  *
5255
5674
  * @remarks
5256
5675
  * Approximates `ceil(length / 4)` (4 characters per token), so the same input always yields the same estimate (no model round-trip).
@@ -6028,6 +6447,20 @@ export declare function isAgentJobError(value: unknown): value is AgentJobError;
6028
6447
  */
6029
6448
  export declare function isAuthorityDecision(value: unknown): value is AuthorityDecision;
6030
6449
 
6450
+ /**
6451
+ * Checks whether a value is an authority verdict: `allow`, `ask`, or `deny`.
6452
+ *
6453
+ * @param value - The unknown verdict candidate
6454
+ * @returns True if the value names a verdict; false otherwise
6455
+ *
6456
+ * @example
6457
+ * ```ts
6458
+ * isAuthorityVerdict('ask') // true
6459
+ * isAuthorityVerdict('maybe') // false
6460
+ * ```
6461
+ */
6462
+ export declare function isAuthorityVerdict(value: unknown): value is AuthorityVerdict;
6463
+
6031
6464
  /**
6032
6465
  * Narrows an unknown caught value to a {@link ContextError} through its identity brand and declared members, so a
6033
6466
  * `catch` can branch on its `code`.
@@ -6097,12 +6530,12 @@ export declare function isConversationError(value: unknown): value is Conversati
6097
6530
  * valid {@link Message} ({@link isMessage}), and optional valid `judgments` — enough to safely
6098
6531
  * impose the
6099
6532
  * {@link ConversationSnapshot} type at a storage boundary without a cast. The structural twin of
6100
- * {@link import('@orkestrel/workspace').isWorkspaceSnapshot}. Unknown members are admitted, so a
6101
- * 0.0.29 snapshot that carries a conversation `summary` passes. A malformed blob (a non-record,
6102
- * a missing / non-string `id`, a non-array `sections` / `messages`, or any malformed
6103
- * element) resolves `false`, so a
6533
+ * {@link import('@orkestrel/workspace').isWorkspaceSnapshot}. The guard is exact: an unknown member, a
6534
+ * 0.0.35 snapshot's conversation `summary` included, and an own `undefined` `judgments` return
6535
+ * `false`, as a malformed blob (a non-record, a missing / non-string `id`, a non-array `sections` /
6536
+ * `messages`, or any malformed element) does, so a
6104
6537
  * {@link import('./stores/DatabaseConversationStore.js').DatabaseConversationStore}
6105
- * read yields `undefined` rather than a broken conversation. The guard is structural: it admits a
6538
+ * read refuses it rather than seating a broken conversation. The guard is structural: it admits a
6106
6539
  * stored `system` role and a repeated id, which `requireConversationSnapshot` and the
6107
6540
  * {@link import('./Conversation.js').Conversation} constructor then refuse as the stored-data
6108
6541
  * check a conversation runs at hydrate.
@@ -6144,14 +6577,37 @@ export declare function isFraction(value: unknown): value is number;
6144
6577
  export declare function isJudgeAbortError(value: unknown): value is JudgeAbortError;
6145
6578
 
6146
6579
  /**
6147
- * Checks whether a value is a judge entry: a string, a JSON record, or a JSON array.
6580
+ * Checks whether a value is a stored judge answer of the choice, score, or noul form.
6581
+ *
6582
+ * @remarks
6583
+ * Total: an untrusted input returns false. The guard is exact on the answer's own keys and reads each
6584
+ * probability as a finite number, with noul bounded to `[0, 1]`. Whether the answer fits
6585
+ * its question belongs to the write. Every
6586
+ * judgment of a hydrate reads this guard, so it counts keys by hand rather than through a built one,
6587
+ * and `judgeAnswerContract` holds it in lockstep: an answer the contract accepts passes here.
6588
+ *
6589
+ * @param value - The value to test
6590
+ * @returns True if the value has the shape of a {@link JudgeAnswer}; false otherwise
6591
+ * @example
6592
+ * ```ts
6593
+ * isJudgeAnswer({ form: 'noul', noul: 0.9 }) // true
6594
+ * isJudgeAnswer({ form: 'choice', probabilities: { billing: 1 } }) // true
6595
+ * isJudgeAnswer({ form: 'noul', noul: 0.9, note: 'extra' }) // false
6596
+ * ```
6597
+ */
6598
+ export declare function isJudgeAnswer(value: unknown): value is JudgeAnswer;
6599
+
6600
+ /**
6601
+ * Checks whether a value is a judge entry: a non-empty string, a non-empty JSON record, or a non-empty
6602
+ * JSON array.
6148
6603
  *
6149
6604
  * @remarks
6150
- * Total: a cycle, a non-JSON member, a class instance, and an untrusted input return false. `null`
6151
- * is not an entry; a criteria guard admits it where the protocol keeps it.
6605
+ * Total: a cycle, a non-JSON member, a class instance, and an untrusted input return false. `''`,
6606
+ * `[]`, and `{}` give a judge nothing to read, so they return false. `null` is not an entry; a
6607
+ * criteria guard admits it where the protocol keeps it.
6152
6608
  *
6153
6609
  * @param value - The unknown entry candidate
6154
- * @returns True if the value is a string or JSON structure the model can read; false otherwise
6610
+ * @returns True if the value is a non-empty string or JSON structure the model can read; false otherwise
6155
6611
  * @example
6156
6612
  * ```ts
6157
6613
  * isJudgeEntry('Customer asks for a refund') // true
@@ -6180,8 +6636,10 @@ export declare function isJudgeError(value: unknown): value is JudgeError;
6180
6636
  * @remarks
6181
6637
  * Total: an untrusted input returns false. A choice needs at least 2 options and a score at least 2
6182
6638
  * levels, because the confidence formula divides by the candidate count; a description or a level
6183
- * can be `null`. `instructions` and noul `criteria` are omitted when absent and never `null`.
6184
- * Server limits on option, level, and question counts are left to the server.
6639
+ * can be `null`. `instructions` and noul `criteria` are omitted when absent and never `null`. The
6640
+ * guard is exact on the question's own keys: an unknown member, and an own `undefined` optional,
6641
+ * return false, as `judgeQuestionContract` does. Server limits on option, level, and question counts
6642
+ * are left to the server.
6185
6643
  *
6186
6644
  * @param value - The unknown question candidate
6187
6645
  * @returns True if the value is a question the judge engine can send; false otherwise
@@ -6199,11 +6657,13 @@ export declare function isJudgeQuestion(value: unknown): value is JudgeQuestion;
6199
6657
  * Checks whether a stored judgment carries a valid question and exactly one answer or refusal.
6200
6658
  *
6201
6659
  * @remarks
6202
- * Unknown members, malformed members, and unreadable inputs return false. Answer fields follow
6203
- * the root judge value types; this storage guard does not impose a wire's probability or
6204
- * candidate limits. The `time`, `noul`, and probability numbers must be finite, because a stored
6205
- * record is owned through JSON, which turns `NaN` and the infinities into `null`; so every record
6206
- * this guard accepts hydrates through a `JudgmentManager`.
6660
+ * Unknown members, malformed members, and unreadable inputs return false, the answer's and the
6661
+ * refusal's own included. Answer fields follow the root judge value types; this storage guard does not
6662
+ * impose a wire's probability or candidate limits, and the ties an answer holds to its question run
6663
+ * where a judgment is written, because records written before them can miss them. The `time`, `noul`,
6664
+ * and probability numbers must be finite, because a stored record is owned through JSON, which turns
6665
+ * `NaN` and the infinities into `null`; so every record this guard accepts hydrates through a
6666
+ * `JudgmentManager`.
6207
6667
  *
6208
6668
  * @param value - The unknown stored record
6209
6669
  * @returns True if the record satisfies the judgment contract; false otherwise
@@ -6229,6 +6689,25 @@ export declare const isJudgment: Guard<Judgment>;
6229
6689
  */
6230
6690
  export declare function isLedgerError(value: unknown): value is LedgerError;
6231
6691
 
6692
+ /**
6693
+ * Checks whether a value holds the wording a ledger files with: a choice `category` question whose
6694
+ * criteria describe every category, a non-empty `topic` string, and noul `amends` and `supersedes`
6695
+ * questions.
6696
+ *
6697
+ * @remarks
6698
+ * A ledger asks these on every message, so a hole in them would otherwise surface as filing that quietly
6699
+ * stays undecided. Total: an unreadable member returns false.
6700
+ *
6701
+ * @param value - The value to inspect
6702
+ * @returns True if the value holds the wording the ledger's questions read; false otherwise
6703
+ * @example
6704
+ * ```ts
6705
+ * isLedgerQuestion(LEDGER_QUESTIONS) // true
6706
+ * isLedgerQuestion({ topic: 'Does it concern this?' }) // false
6707
+ * ```
6708
+ */
6709
+ export declare function isLedgerQuestion(value: unknown): value is LedgerQuestion;
6710
+
6232
6711
  /**
6233
6712
  * Checks whether a value is a ledger snapshot whose marked ids name messages of its own conversation.
6234
6713
  *
@@ -6237,8 +6716,9 @@ export declare function isLedgerError(value: unknown): value is LedgerError;
6237
6716
  * dense arrays of strings. Each request and note id must name a `user` message of
6238
6717
  * `conversation.messages` and each failure id a `tool` message, so an id only a section original
6239
6718
  * holds is refused. A `gauge`, when present, must hold a finite `scale` greater than 0 and a finite
6240
- * `overhead` of at least 0. Unknown members are admitted. Unreadable members and untrusted inputs
6241
- * return false. The guard is structural: it admits a conversation holding a stored `system` role
6719
+ * `overhead` of at least 0. The guard is exact: an unknown member and an own `undefined` `gauge` return
6720
+ * false, at the snapshot and in its `gauge`. Unreadable members and untrusted inputs return false. The
6721
+ * guard is structural: it admits a conversation holding a stored `system` role
6242
6722
  * or a repeated id, which `requireConversationSnapshot` and the `Conversation` constructor then
6243
6723
  * refuse as the stored-data check a ledger's hydrate runs.
6244
6724
  *
@@ -6259,9 +6739,11 @@ export declare function isLedgerSnapshot(value: unknown): value is LedgerSnapsho
6259
6739
  *
6260
6740
  * @remarks
6261
6741
  * An `origin`, when present, is a record with a string `conversation` and an optional string
6262
- * `message`. Unknown members are admitted. The `time` must be finite, because a stored revision
6263
- * is owned through JSON, which turns `NaN` and the infinities into `null`. Malformed and
6264
- * unreadable inputs, a throwing getter or a revoked proxy included, return false.
6742
+ * `message`. The guard is exact: an unknown member and an own `undefined` optional return false. The
6743
+ * `time` must be finite, because a stored revision is owned through JSON, which turns `NaN` and the
6744
+ * infinities into `null`. Malformed and unreadable inputs, a throwing getter or a revoked proxy
6745
+ * included, return false. Every revision of a hydrate reads this guard, so it counts keys by hand
6746
+ * rather than through a built one, and `memoSnapshotContract` holds it in lockstep.
6265
6747
  *
6266
6748
  * @param value - The value to test
6267
6749
  * @returns True if `value` has the shape of a {@link Memo}; false otherwise
@@ -6274,18 +6756,36 @@ export declare function isLedgerSnapshot(value: unknown): value is LedgerSnapsho
6274
6756
  * isMemo({ id: 'm1', name: 'tone', description: 'Prefers short replies.', content: 'Answer briefly.', time: Number.NaN }) // false
6275
6757
  * ```
6276
6758
  */
6277
- export declare const isMemo: Guard<Memo>;
6759
+ export declare function isMemo(value: unknown): value is Memo;
6278
6760
 
6279
6761
  /**
6280
- * Checks whether a value is a stored memo set: a record with a string `id` and a dense `memos`
6281
- * array of {@link isMemo} values.
6762
+ * Checks whether a value is a memo's origin: a record with a string `conversation` and an optional
6763
+ * string `message`.
6282
6764
  *
6283
6765
  * @remarks
6284
- * Unknown members are admitted. A sparse `memos` array, a malformed revision, and unreadable
6285
- * inputs, a throwing getter or a revoked proxy included, return false.
6766
+ * The guard is exact: an unknown member and an own `undefined` `message` return false. Malformed and
6767
+ * unreadable inputs return false.
6286
6768
  *
6287
- * @param value - The value to test (an opaque storage read)
6288
- * @returns True if `value` has the shape of a {@link MemoSnapshot}; false otherwise
6769
+ * @param value - The value to test
6770
+ * @returns True if `value` has the shape of a {@link MemoOrigin}; false otherwise
6771
+ * @example
6772
+ * ```ts
6773
+ * isMemoOrigin({ conversation: 'c1', message: 'm1' }) // true
6774
+ * isMemoOrigin({ conversation: 'c1', extra: true }) // false
6775
+ * ```
6776
+ */
6777
+ export declare function isMemoOrigin(value: unknown): value is MemoOrigin;
6778
+
6779
+ /**
6780
+ * Checks whether a value is a stored memo set: a record with a string `id` and a dense `memos`
6781
+ * array of {@link isMemo} values.
6782
+ *
6783
+ * @remarks
6784
+ * The guard is exact: an unknown member returns false, as a sparse `memos` array, a malformed
6785
+ * revision, and unreadable inputs, a throwing getter or a revoked proxy included, do.
6786
+ *
6787
+ * @param value - The value to test (an opaque storage read)
6788
+ * @returns True if `value` has the shape of a {@link MemoSnapshot}; false otherwise
6289
6789
  *
6290
6790
  * @example
6291
6791
  * ```ts
@@ -6303,8 +6803,9 @@ export declare function isMemoSnapshot(value: unknown): value is MemoSnapshot;
6303
6803
  * @remarks
6304
6804
  * Roles belong to MessageRole, image elements are strings, `thinking` is a string, and `call` is a string on any
6305
6805
  * role, as the flat Message type admits. Tool arguments may carry non-JSON values, as the
6306
- * domain type permits; the message wire contract is narrower. Unreadable fields and untrusted
6307
- * inputs return false.
6806
+ * domain type permits; the message wire contract is narrower. The guard is exact on the message's own
6807
+ * keys: an unknown member, and an own `undefined` optional, return false. Unreadable fields and
6808
+ * untrusted inputs return false.
6308
6809
  *
6309
6810
  * @param value - The unknown message candidate
6310
6811
  * @returns True if the domain message fields are valid; false otherwise
@@ -6318,6 +6819,25 @@ export declare function isMemoSnapshot(value: unknown): value is MemoSnapshot;
6318
6819
  */
6319
6820
  export declare function isMessage(value: unknown): value is Message;
6320
6821
 
6822
+ /**
6823
+ * Checks whether a value is a message input a conversation can store: a string `content`, and `calls`,
6824
+ * `call`, `images`, and `thinking` absent or of their declared types.
6825
+ *
6826
+ * @remarks
6827
+ * A hand guard, because `add` checks every message: it reads the members once and composes no record
6828
+ * guard. The role is `requireRole`'s to refuse, so its text can name the role received. Unknown members
6829
+ * are left behind by the store. An unreadable member returns false.
6830
+ *
6831
+ * @param value - The unknown input candidate
6832
+ * @returns True if the input's members are valid; false otherwise
6833
+ * @example
6834
+ * ```ts
6835
+ * isMessageInput({ role: 'user', content: 'hi' }) // true
6836
+ * isMessageInput({ role: 'user' }) // false
6837
+ * ```
6838
+ */
6839
+ export declare function isMessageInput(value: unknown): value is MessageInput;
6840
+
6321
6841
  /**
6322
6842
  * Checks whether a value is a non-negative safe integer, `-0` included.
6323
6843
  *
@@ -6346,6 +6866,7 @@ export declare function isNonNegativeSafeInteger(value: unknown): value is numbe
6346
6866
  * @example
6347
6867
  * ```ts
6348
6868
  * isPositiveSafeInteger(4096) // true
6869
+ * isPositiveSafeInteger(0) // false
6349
6870
  * ```
6350
6871
  */
6351
6872
  export declare function isPositiveSafeInteger(value: unknown): value is number;
@@ -6380,6 +6901,28 @@ export declare function isProviderAbortError(value: unknown): value is ProviderA
6380
6901
  */
6381
6902
  export declare function isProviderError(value: unknown): value is ProviderError;
6382
6903
 
6904
+ /**
6905
+ * Checks whether a value carries the members {@link ProviderResult} publishes: a string `content`, and
6906
+ * `thinking`, `tools`, `usage`, and `truncated` absent or of their published types.
6907
+ *
6908
+ * @remarks
6909
+ * A provider is a foreign interface, so the guard is open: unknown members and a class instance pass,
6910
+ * and each `usage` count is a finite nonnegative number with no integer check. An unreadable member
6911
+ * returns false. {@link import('./helpers.js').requireProviderResult} runs it on an owned copy, the one
6912
+ * door a run's result crosses.
6913
+ *
6914
+ * @param value - The unknown result candidate
6915
+ * @returns True if the value satisfies the published result; false otherwise
6916
+ *
6917
+ * @example
6918
+ * ```ts
6919
+ * isProviderResult({ content: 'answer', extra: true }) // true
6920
+ * isProviderResult({}) // false
6921
+ * isProviderResult({ content: 'answer', usage: { prompt: -1, completion: 0, total: 0 } }) // false
6922
+ * ```
6923
+ */
6924
+ export declare const isProviderResult: Guard<ProviderResult>;
6925
+
6383
6926
  /**
6384
6927
  * Checks whether an `unknown` is structurally a {@link Section} record — a `string` `id` and
6385
6928
  * `summary` beside a `messages` array of valid {@link Message} records, the per-section step of
@@ -6390,8 +6933,8 @@ export declare function isProviderError(value: unknown): value is ProviderError;
6390
6933
  * A total guard (it never throws — untrusted input, a throwing getter included, returns
6391
6934
  * `false`). It checks the shape of the section: a record with a `string` `id`, a `string`
6392
6935
  * `summary`, and a dense `messages` array every element of which is a valid {@link Message}
6393
- * record ({@link isMessage}); a sparse `messages` array is refused. Enough to safely impose
6394
- * the {@link Section} type at a storage boundary without a cast.
6936
+ * record ({@link isMessage}), and no other member; a sparse `messages` array is refused. Enough to
6937
+ * safely impose the {@link Section} type at a storage boundary without a cast.
6395
6938
  *
6396
6939
  * @param value - The value to test (one element of a snapshot's `sections` array)
6397
6940
  * @returns True if `value` has the structural shape of a {@link Section}; false otherwise
@@ -6489,9 +7032,50 @@ export declare class JudgeAbortError extends Error {
6489
7032
  /** Names one answer by its form; it stores only the distribution a server returned. */
6490
7033
  export declare type JudgeAnswer = ChoiceAnswer | ScoreAnswer | NoulAnswer;
6491
7034
 
7035
+ /** Reads the faults of a refused judge answer. */
7036
+ export declare const judgeAnswerContract: ContractInterface<Readonly<{
7037
+ form: "choice";
7038
+ probabilities: {
7039
+ readonly [k: string]: number;
7040
+ };
7041
+ } & {}> | Readonly<{
7042
+ form: "score";
7043
+ probabilities: readonly number[];
7044
+ } & {}> | Readonly<{
7045
+ form: "noul";
7046
+ noul: number;
7047
+ } & {}>>;
7048
+
7049
+ /**
7050
+ * Describes a judge answer: one exact object per form, each probability in `[0, 1]`.
7051
+ *
7052
+ * @remarks
7053
+ * The ties an answer holds to its question run at the write doors through `scanJudgmentTies`, which a
7054
+ * shape over the answer alone cannot state.
7055
+ */
7056
+ export declare const judgeAnswerShape: UnionShape<readonly [ObjectShape< {
7057
+ form: LiteralShape<readonly ["choice"]>;
7058
+ probabilities: ObjectShape<Record<never, never>, NumberShape>;
7059
+ }, boolean | ContractShape>, ObjectShape< {
7060
+ form: LiteralShape<readonly ["score"]>;
7061
+ probabilities: ArrayShape<NumberShape>;
7062
+ }, boolean | ContractShape>, ObjectShape< {
7063
+ form: LiteralShape<readonly ["noul"]>;
7064
+ noul: NumberShape;
7065
+ }, boolean | ContractShape>]>;
7066
+
6492
7067
  /** Carries text or structured JSON the model reads; mirrors the TypeSafe `EntryType` without its null arm. */
6493
7068
  export declare type JudgeEntry = string | JSONRecord | readonly JSONValue[];
6494
7069
 
7070
+ /**
7071
+ * Describes the text or JSON a judge reads: a non-empty string, a non-empty JSON array, or a JSON record.
7072
+ *
7073
+ * @remarks
7074
+ * A shape has no `minProperties`, so this one admits the empty record that `isJudgeEntry` refuses;
7075
+ * the guard is the door, and this shape only fills a refusal's faults.
7076
+ */
7077
+ export declare const judgeEntryShape: UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>;
7078
+
6495
7079
  /**
6496
7080
  * Reports a coded judge failure with its HTTP status and underlying cause when available.
6497
7081
  *
@@ -6506,6 +7090,8 @@ export declare class JudgeError extends Error {
6506
7090
  readonly code: JudgeErrorCode;
6507
7091
  /** Holds the response status for an HTTP failure, or undefined for other codes. */
6508
7092
  readonly status: number | undefined;
7093
+ /** Holds the values that locate the failure, such as the `faults` of a refused question, or `undefined` when none were supplied. */
7094
+ readonly context: Readonly<Record<string, unknown>> | undefined;
6509
7095
  constructor(code: JudgeErrorCode, message: string, options?: ProviderErrorOptions);
6510
7096
  }
6511
7097
 
@@ -6531,6 +7117,67 @@ export declare interface JudgeInterface {
6531
7117
  /** Names one question by its form, the protocol's type field under the fleet's named discriminant. */
6532
7118
  export declare type JudgeQuestion = ChoiceQuestion | ScoreQuestion | NoulQuestion;
6533
7119
 
7120
+ /** Reads the faults of a refused judge question. */
7121
+ export declare const judgeQuestionContract: ContractInterface<Readonly<{
7122
+ form: "choice";
7123
+ criteria: {
7124
+ readonly [k: string]: string | readonly JSONValue[] | {
7125
+ readonly [k: string]: JSONValue;
7126
+ } | null;
7127
+ };
7128
+ } & {
7129
+ instructions?: string | readonly JSONValue[] | {
7130
+ readonly [k: string]: JSONValue;
7131
+ };
7132
+ }> | Readonly<{
7133
+ form: "score";
7134
+ criteria: readonly (string | readonly JSONValue[] | {
7135
+ readonly [k: string]: JSONValue;
7136
+ } | null)[];
7137
+ } & {
7138
+ instructions?: string | readonly JSONValue[] | {
7139
+ readonly [k: string]: JSONValue;
7140
+ };
7141
+ }> | Readonly<{
7142
+ form: "noul";
7143
+ } & {
7144
+ instructions?: string | readonly JSONValue[] | {
7145
+ readonly [k: string]: JSONValue;
7146
+ };
7147
+ criteria?: Readonly<{} & {
7148
+ true?: string | readonly JSONValue[] | {
7149
+ readonly [k: string]: JSONValue;
7150
+ };
7151
+ false?: string | readonly JSONValue[] | {
7152
+ readonly [k: string]: JSONValue;
7153
+ };
7154
+ }>;
7155
+ }>>;
7156
+
7157
+ /**
7158
+ * Describes a judge question: one exact object per form, the schema an LLM-facing wire can publish.
7159
+ *
7160
+ * @remarks
7161
+ * `isJudgeQuestion` is the door; this shape fills a refusal's faults. A choice needing at least 2
7162
+ * options is the guard's alone, because a shape has no `minProperties`.
7163
+ */
7164
+ export declare const judgeQuestionShape: UnionShape<readonly [ObjectShape< {
7165
+ form: LiteralShape<readonly ["choice"]>;
7166
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7167
+ criteria: ObjectShape<Record<never, never>, NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
7168
+ }, boolean | ContractShape>, ObjectShape< {
7169
+ form: LiteralShape<readonly ["score"]>;
7170
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7171
+ criteria: ArrayShape<NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
7172
+ }, boolean | ContractShape>, ObjectShape< {
7173
+ form: LiteralShape<readonly ["noul"]>;
7174
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7175
+ criteria: OptionalShape<ObjectShape< {
7176
+ true: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7177
+ false: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7178
+ }, boolean | ContractShape>>;
7179
+ }, boolean | ContractShape>]>;
7180
+
6534
7181
  /** Carries one state and the questions asked about it, keyed by caller ids the prompt never carries; each question is evaluated on its own. */
6535
7182
  export declare interface JudgeRequest {
6536
7183
  readonly state: JudgeEntry;
@@ -6562,6 +7209,118 @@ export declare interface Judgment {
6562
7209
  readonly usage?: TokenUsage;
6563
7210
  }
6564
7211
 
7212
+ /** Reads the faults of a refused judgment. */
7213
+ export declare const judgmentContract: ContractInterface<Readonly<{
7214
+ id: string;
7215
+ question: Readonly<{
7216
+ form: "choice";
7217
+ criteria: {
7218
+ readonly [k: string]: string | readonly JSONValue[] | {
7219
+ readonly [k: string]: JSONValue;
7220
+ } | null;
7221
+ };
7222
+ } & {
7223
+ instructions?: string | readonly JSONValue[] | {
7224
+ readonly [k: string]: JSONValue;
7225
+ };
7226
+ }> | Readonly<{
7227
+ form: "score";
7228
+ criteria: readonly (string | readonly JSONValue[] | {
7229
+ readonly [k: string]: JSONValue;
7230
+ } | null)[];
7231
+ } & {
7232
+ instructions?: string | readonly JSONValue[] | {
7233
+ readonly [k: string]: JSONValue;
7234
+ };
7235
+ }> | Readonly<{
7236
+ form: "noul";
7237
+ } & {
7238
+ instructions?: string | readonly JSONValue[] | {
7239
+ readonly [k: string]: JSONValue;
7240
+ };
7241
+ criteria?: Readonly<{} & {
7242
+ true?: string | readonly JSONValue[] | {
7243
+ readonly [k: string]: JSONValue;
7244
+ };
7245
+ false?: string | readonly JSONValue[] | {
7246
+ readonly [k: string]: JSONValue;
7247
+ };
7248
+ }>;
7249
+ }>;
7250
+ model: string;
7251
+ sources: readonly string[];
7252
+ state: string;
7253
+ time: number;
7254
+ answer: Readonly<{
7255
+ form: "choice";
7256
+ probabilities: {
7257
+ readonly [k: string]: number;
7258
+ };
7259
+ } & {}> | Readonly<{
7260
+ form: "score";
7261
+ probabilities: readonly number[];
7262
+ } & {}> | Readonly<{
7263
+ form: "noul";
7264
+ noul: number;
7265
+ } & {}>;
7266
+ } & {
7267
+ usage?: Readonly<{
7268
+ prompt: number;
7269
+ completion: number;
7270
+ total: number;
7271
+ } & {}>;
7272
+ }> | Readonly<{
7273
+ id: string;
7274
+ question: Readonly<{
7275
+ form: "choice";
7276
+ criteria: {
7277
+ readonly [k: string]: string | readonly JSONValue[] | {
7278
+ readonly [k: string]: JSONValue;
7279
+ } | null;
7280
+ };
7281
+ } & {
7282
+ instructions?: string | readonly JSONValue[] | {
7283
+ readonly [k: string]: JSONValue;
7284
+ };
7285
+ }> | Readonly<{
7286
+ form: "score";
7287
+ criteria: readonly (string | readonly JSONValue[] | {
7288
+ readonly [k: string]: JSONValue;
7289
+ } | null)[];
7290
+ } & {
7291
+ instructions?: string | readonly JSONValue[] | {
7292
+ readonly [k: string]: JSONValue;
7293
+ };
7294
+ }> | Readonly<{
7295
+ form: "noul";
7296
+ } & {
7297
+ instructions?: string | readonly JSONValue[] | {
7298
+ readonly [k: string]: JSONValue;
7299
+ };
7300
+ criteria?: Readonly<{} & {
7301
+ true?: string | readonly JSONValue[] | {
7302
+ readonly [k: string]: JSONValue;
7303
+ };
7304
+ false?: string | readonly JSONValue[] | {
7305
+ readonly [k: string]: JSONValue;
7306
+ };
7307
+ }>;
7308
+ }>;
7309
+ model: string;
7310
+ sources: readonly string[];
7311
+ state: string;
7312
+ time: number;
7313
+ refusal: Readonly<{
7314
+ missing: readonly string[];
7315
+ } & {}>;
7316
+ } & {
7317
+ usage?: Readonly<{
7318
+ prompt: number;
7319
+ completion: number;
7320
+ total: number;
7321
+ } & {}>;
7322
+ }>>;
7323
+
6565
7324
  /** Supplies an answered or refused question for storage before its time is stamped. */
6566
7325
  export declare interface JudgmentInput {
6567
7326
  readonly id: string;
@@ -6661,6 +7420,83 @@ export declare interface JudgmentManagerInterface {
6661
7420
  resolve(judge: JudgeInterface, request: JudgeRequest, sources: readonly string[], signal: AbortSignal): Promise<readonly Judgment[]>;
6662
7421
  }
6663
7422
 
7423
+ /**
7424
+ * Describes a stored judgment: exactly one of an answer or a refusal, with its question, sources,
7425
+ * state, model, and storage time.
7426
+ *
7427
+ * @remarks
7428
+ * `isJudgment` is the door a hydrate reads and this shape fills a refusal's faults, because hydrate is
7429
+ * a per-element path. A lockstep test holds that `is` implies the guard.
7430
+ */
7431
+ export declare const judgmentShape: UnionShape<readonly [ObjectShape< {
7432
+ id: StringShape;
7433
+ question: UnionShape<readonly [ObjectShape< {
7434
+ form: LiteralShape<readonly ["choice"]>;
7435
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7436
+ criteria: ObjectShape<Record<never, never>, NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
7437
+ }, boolean | ContractShape>, ObjectShape< {
7438
+ form: LiteralShape<readonly ["score"]>;
7439
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7440
+ criteria: ArrayShape<NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
7441
+ }, boolean | ContractShape>, ObjectShape< {
7442
+ form: LiteralShape<readonly ["noul"]>;
7443
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7444
+ criteria: OptionalShape<ObjectShape< {
7445
+ true: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7446
+ false: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7447
+ }, boolean | ContractShape>>;
7448
+ }, boolean | ContractShape>]>;
7449
+ model: StringShape;
7450
+ sources: ArrayShape<StringShape>;
7451
+ state: StringShape;
7452
+ time: NumberShape;
7453
+ usage: OptionalShape<ObjectShape< {
7454
+ prompt: NumberShape;
7455
+ completion: NumberShape;
7456
+ total: NumberShape;
7457
+ }, boolean | ContractShape>>;
7458
+ answer: UnionShape<readonly [ObjectShape< {
7459
+ form: LiteralShape<readonly ["choice"]>;
7460
+ probabilities: ObjectShape<Record<never, never>, NumberShape>;
7461
+ }, boolean | ContractShape>, ObjectShape< {
7462
+ form: LiteralShape<readonly ["score"]>;
7463
+ probabilities: ArrayShape<NumberShape>;
7464
+ }, boolean | ContractShape>, ObjectShape< {
7465
+ form: LiteralShape<readonly ["noul"]>;
7466
+ noul: NumberShape;
7467
+ }, boolean | ContractShape>]>;
7468
+ }, boolean | ContractShape>, ObjectShape< {
7469
+ id: StringShape;
7470
+ question: UnionShape<readonly [ObjectShape< {
7471
+ form: LiteralShape<readonly ["choice"]>;
7472
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7473
+ criteria: ObjectShape<Record<never, never>, NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
7474
+ }, boolean | ContractShape>, ObjectShape< {
7475
+ form: LiteralShape<readonly ["score"]>;
7476
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7477
+ criteria: ArrayShape<NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
7478
+ }, boolean | ContractShape>, ObjectShape< {
7479
+ form: LiteralShape<readonly ["noul"]>;
7480
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7481
+ criteria: OptionalShape<ObjectShape< {
7482
+ true: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7483
+ false: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
7484
+ }, boolean | ContractShape>>;
7485
+ }, boolean | ContractShape>]>;
7486
+ model: StringShape;
7487
+ sources: ArrayShape<StringShape>;
7488
+ state: StringShape;
7489
+ time: NumberShape;
7490
+ usage: OptionalShape<ObjectShape< {
7491
+ prompt: NumberShape;
7492
+ completion: NumberShape;
7493
+ total: NumberShape;
7494
+ }, boolean | ContractShape>>;
7495
+ refusal: ObjectShape< {
7496
+ missing: ArrayShape<StringShape>;
7497
+ }, boolean | ContractShape>;
7498
+ }, boolean | ContractShape>]>;
7499
+
6664
7500
  /**
6665
7501
  * Serves one conversation through classified records, a bounded copy of each request turn that carries them, and a final answer pass.
6666
7502
  * @example
@@ -6678,7 +7514,8 @@ export declare class Ledger implements LedgerInterface {
6678
7514
  * @param options - The filing policy, capacity, and request bounds
6679
7515
  * @throws {LedgerError} Thrown when a threshold, share, capacity, limit, topic, lookup, or gauge is invalid
6680
7516
  * @throws {LedgerError} Thrown when `predict` is not a nonnegative safe integer less than `capacity` (code `'CAPACITY'`)
6681
- * @throws {LedgerError} Thrown when `snapshot` is malformed or marks an id its conversation does not hold (code `'SNAPSHOT'`)
7517
+ * @throws {LedgerError} Thrown when `questions` fails `isLedgerQuestion` (code `'QUESTION'`)
7518
+ * @throws {LedgerError} Thrown when `snapshot` is malformed or marks an id its conversation does not hold (code `'SNAPSHOT'`, its faults under `context.faults`)
6682
7519
  * @throws {ConversationError} Thrown when `isLedgerSnapshot` admits `snapshot` but its conversation holds a `system` message (code `'ROLE'`) or repeats an id (code `'SNAPSHOT'`)
6683
7520
  */
6684
7521
  constructor(provider: ProviderInterface, options: LedgerOptions);
@@ -6714,7 +7551,7 @@ export declare class Ledger implements LedgerInterface {
6714
7551
  /**
6715
7552
  * Appends a request and serves it, recovering an unfinished or rejected first pass with one answer pass.
6716
7553
  * A calibration call that reports no prompt usage, or a prompt usage of 0 or less, rejects with `LedgerError` code `'GAUGE'`; a provider error during calibration rejects with that error.
6717
- * When the answer pass rejects, `respond` rejects with that error. Every rejection leaves the ledger free for a later call.
7554
+ * When the answer pass rejects, `respond` rejects with that error, and under the default `strict` a judge failure or another selection failure rejects it too. A rejection belongs to its own call: the ledger stays free, and the next call asks the judge again about whatever is still unanswered.
6718
7555
  * @param content - The request text
6719
7556
  * @param signal - The caller's cancellation signal; an abort during calibration rejects with its reason
6720
7557
  * @returns The final pass, the usage of every pass, and the filing attempts of this request alone
@@ -6783,15 +7620,19 @@ export declare const LEDGER_WORD: RegExp;
6783
7620
  * Selects the agent bounds, hooks, scheduler, and context libraries a ledger passes through to the agent it builds.
6784
7621
  *
6785
7622
  * @remarks
6786
- * `limit` must be a nonnegative safe integer. Default: the `DEFAULT_LEDGER_LIMIT` constant. The
7623
+ * `limit` must be a positive safe integer. Default: the `DEFAULT_LEDGER_LIMIT` constant. The
6787
7624
  * ledger owns every other agent option: the conversation, the tools, the selection handler, and
6788
7625
  * the scope. One memo set can serve many ledgers of one principal, and the plan prices what these
6789
7626
  * libraries add to the head. `scheduler` also reaches the ledger's classifier, which hands the host
6790
7627
  * a turn while it files, so a page passes it to keep the filing out of one long task. The classifier
6791
7628
  * and the loop race its yield against the run signal, so a scheduler that ignores its signal still
6792
- * ends on a cancel.
7629
+ * ends on a cancel. `strict` defaults to `true`: a judge failure or another selection failure rejects
7630
+ * that `respond` call after the `fault` event, and the next call asks the judge again about whatever is
7631
+ * still unanswered. With `strict: false` the request goes on with that question undecided, or from the
7632
+ * conversation's `view()`. A provider failure in the first pass is the one
7633
+ * failure the answer pass recovers under either value.
6793
7634
  */
6794
- export declare type LedgerAgentOptions = Pick<AgentOptions, 'limit' | 'timeout' | 'on' | 'scheduler' | 'instructions' | 'skills' | 'memos' | 'workspaces'>;
7635
+ export declare type LedgerAgentOptions = Pick<AgentOptions, 'limit' | 'timeout' | 'on' | 'scheduler' | 'instructions' | 'skills' | 'memos' | 'workspaces' | 'strict'>;
6795
7636
 
6796
7637
  /** Identifies an accepted direct message amendment whose sentence scope remains unresolved. */
6797
7638
  export declare interface LedgerAmendment {
@@ -6853,10 +7694,10 @@ export declare type LedgerEntityHandler = (text: string, partial: boolean) => Re
6853
7694
  * carrying the machine-readable `code`.
6854
7695
  *
6855
7696
  * @remarks
6856
- * A threshold, share, capacity, limit, topic, lookup, or gauge outside its bounds is a programmer
6857
- * error and throws this with the matching {@link LedgerErrorCode}. A calibration call that reports
7697
+ * A threshold, share, capacity, limit, topic, lookup, question, or gauge outside its bounds is a
7698
+ * programmer error and throws this with the matching {@link LedgerErrorCode}. A calibration call that reports
6858
7699
  * no prompt usage throws this with `'GAUGE'`. A snapshot option that `isLedgerSnapshot` refuses
6859
- * throws this with `'SNAPSHOT'`. Narrow a caught value with {@link isLedgerError} and
7700
+ * throws this with `'SNAPSHOT'`, its `context` holding the `faults`. Narrow a caught value with {@link isLedgerError} and
6860
7701
  * branch on `error.code`. A selection without an active `respond` call, for a conversation other
6861
7702
  * than the ledger's, or for a request other than that call's request or a ledger note, reports
6862
7703
  * `'REQUEST'` through the selection's fault.
@@ -6864,13 +7705,16 @@ export declare type LedgerEntityHandler = (text: string, partial: boolean) => Re
6864
7705
  export declare class LedgerError extends Error {
6865
7706
  /** Names the machine-readable condition; the {@link LedgerErrorCode} union describes each code. */
6866
7707
  readonly code: LedgerErrorCode;
7708
+ /** Holds the values that locate the failure, such as the `faults` of a refused snapshot, or `undefined` when none were supplied. */
7709
+ readonly context: Readonly<Record<string, unknown>> | undefined;
6867
7710
  /**
6868
7711
  * Records the failure condition and its description.
6869
7712
  *
6870
7713
  * @param code - The machine-readable condition, exposed as `error.code`
6871
7714
  * @param message - The human-readable description of the failure
7715
+ * @param options - The optional {@link CodedErrorOptions}; `cause` reaches `Error.cause` only when present
6872
7716
  */
6873
- constructor(code: LedgerErrorCode, message: string);
7717
+ constructor(code: LedgerErrorCode, message: string, options?: CodedErrorOptions);
6874
7718
  }
6875
7719
 
6876
7720
  /** Names the machine-readable conditions a `LedgerError` error reports. */
@@ -6883,7 +7727,7 @@ export declare type LedgerErrorCode =
6883
7727
  | 'SHARE'
6884
7728
  /** Reports an invalid capacity or a generation cap that is not a nonnegative safe integer less than capacity. */
6885
7729
  | 'CAPACITY'
6886
- /** Reports a recall limit or an agent limit that is not a nonnegative safe integer. */
7730
+ /** Reports a recall limit that is not a nonnegative safe integer, or an agent limit that is not a positive safe integer. */
6887
7731
  | 'LIMIT'
6888
7732
  /** Reports a topic with an empty name or a name another topic carries. */
6889
7733
  | 'TOPIC'
@@ -6894,7 +7738,9 @@ export declare type LedgerErrorCode =
6894
7738
  /** Reports a render context that holds no reference for a source it annotates. */
6895
7739
  | 'REFERENCE'
6896
7740
  /** Reports a snapshot that is malformed or that marks an id its conversation does not hold. */
6897
- | 'SNAPSHOT';
7741
+ | 'SNAPSHOT'
7742
+ /** Reports filing wording that `isLedgerQuestion` refuses. */
7743
+ | 'QUESTION';
6898
7744
 
6899
7745
  /**
6900
7746
  * Carries the price of a prompt in tokens, measured against the model the ledger serves.
@@ -6967,14 +7813,15 @@ export declare interface LedgerInterface {
6967
7813
  * rejects with an `AgentError` whose `code` is `'CONCURRENCY'`. A calibration call that reports no prompt usage, or a prompt usage of 0 or less, rejects with
6968
7814
  * `LedgerError` code `'GAUGE'`; a provider error during calibration rejects with that error.
6969
7815
  * A direct agent run on `conversation` while a `respond` call's pass runs is refused with an
6970
- * `AgentError` whose `code` is `'CONCURRENCY'`; during the calibration that opens the call it is a
6971
- * run no active `respond` call owns. The ledger's agent serves only `conversation`: a run on
6972
- * another conversation started during a `respond` call gets no ledger selection, yet adds its
6973
- * turns and usage to that call's gauge readings and shares its repeat stop, and it can still
6974
- * reach the `recall` and lookup tools, which read `conversation`. The ledger's own guard refuses
6975
- * only `respond`, `calibrate`, and `snapshot` calls.
6976
- * A run no `respond` call owns, including a run during calibration, reads no request's state:
6977
- * its lookup and `recall` calls run with no repeat stop, recall limit, or close rule.
7816
+ * `AgentError` whose `code` is `'CONCURRENCY'`. Under the default `strict`, any other run no active
7817
+ * `respond` call owns rejects with a `LedgerError` whose `code` is `'REQUEST'`: a direct run between
7818
+ * requests, one during calibration, and a run on another conversation during a call. Under
7819
+ * `strict: false` that run goes on over the whole view with no ledger selection; a run on another
7820
+ * conversation then adds its turns and usage to that call's gauge readings and shares its repeat
7821
+ * stop, and it can still reach the `recall` and lookup tools, which read `conversation`. The
7822
+ * ledger's own guard refuses only `respond`, `calibrate`, and `snapshot` calls.
7823
+ * Under `strict: false`, a run no `respond` call owns, including a run during calibration, reads no
7824
+ * request's state: its lookup and `recall` calls run with no repeat stop, recall limit, or close rule.
6978
7825
  * Every rejection leaves the ledger free for a later call.
6979
7826
  *
6980
7827
  * @param content - The request text
@@ -7368,6 +8215,8 @@ export declare class LedgerRequest implements LedgerRequestInterface {
7368
8215
  observe(call: GaugeCall, position: number): void;
7369
8216
  spend(usage: TokenUsage): void;
7370
8217
  think(messages: readonly Message[]): void;
8218
+ fault(error: unknown): void;
8219
+ faulted(error: unknown): boolean;
7371
8220
  file(attempts: readonly ClassifierAttempt[], plan?: Selection): void;
7372
8221
  admit(name: string, args: Readonly<Record<string, unknown>>): void;
7373
8222
  recall(): void;
@@ -7389,6 +8238,15 @@ export declare class LedgerRequest implements LedgerRequestInterface {
7389
8238
  * thinking, until its pass observes the next call, and is final from then on.
7390
8239
  */
7391
8240
  export declare interface LedgerRequestInterface {
8241
+ /** Records an error the request's run reported through its `fault` event. */
8242
+ fault(error: unknown): void;
8243
+ /**
8244
+ * Reports whether the request's run reported this error through its `fault` event.
8245
+ *
8246
+ * @param error - The value a pass rejected with
8247
+ * @returns True if the run reported it; false otherwise
8248
+ */
8249
+ faulted(error: unknown): boolean;
7392
8250
  /** Holds the request message, or undefined until `enter` appends it. */
7393
8251
  readonly message: Message | undefined;
7394
8252
  /** Holds the selection the request's last successful plan produced, or undefined before one. */
@@ -7528,8 +8386,8 @@ export declare interface LedgerShare {
7528
8386
  * of `conversation.messages`: a request or note a `user` message and a failure a `tool` message.
7529
8387
  * `gauge` carries the scale and overhead alone. The gauge's observations of earlier requests are
7530
8388
  * not carried, so a hydrated ledger sizes and closes `recall` from its fallback reserve until it
7531
- * completes a request. A question the classifier held after a deterministic judge failure is not
7532
- * carried, so a hydrated ledger asks it again. Hydrating a second ledger from one snapshot forks
8389
+ * completes a request. A question a `strict: false` classifier held after a deterministic judge
8390
+ * failure is not carried, so a hydrated ledger asks it again. Hydrating a second ledger from one snapshot forks
7533
8391
  * it at the parent's frontier.
7534
8392
  */
7535
8393
  export declare interface LedgerSnapshot {
@@ -7540,6 +8398,288 @@ export declare interface LedgerSnapshot {
7540
8398
  readonly gauge?: LedgerGauge;
7541
8399
  }
7542
8400
 
8401
+ /** Reads the faults of a refused ledger snapshot. */
8402
+ export declare const ledgerSnapshotContract: ContractInterface<Readonly<{
8403
+ conversation: Readonly<{
8404
+ id: string;
8405
+ sections: readonly Readonly<{
8406
+ id: string;
8407
+ summary: string;
8408
+ messages: readonly Readonly<{
8409
+ id: string;
8410
+ role: "assistant" | "system" | "tool" | "user";
8411
+ content: string;
8412
+ } & {
8413
+ calls?: readonly Readonly<{
8414
+ id: string;
8415
+ name: string;
8416
+ arguments: {
8417
+ readonly [k: string]: JSONValue;
8418
+ };
8419
+ } & {}>[];
8420
+ call?: string;
8421
+ images?: readonly string[];
8422
+ thinking?: string;
8423
+ }>[];
8424
+ } & {}>[];
8425
+ messages: readonly Readonly<{
8426
+ id: string;
8427
+ role: "assistant" | "system" | "tool" | "user";
8428
+ content: string;
8429
+ } & {
8430
+ calls?: readonly Readonly<{
8431
+ id: string;
8432
+ name: string;
8433
+ arguments: {
8434
+ readonly [k: string]: JSONValue;
8435
+ };
8436
+ } & {}>[];
8437
+ call?: string;
8438
+ images?: readonly string[];
8439
+ thinking?: string;
8440
+ }>[];
8441
+ } & {
8442
+ judgments?: readonly (Readonly<{
8443
+ id: string;
8444
+ question: Readonly<{
8445
+ form: "choice";
8446
+ criteria: {
8447
+ readonly [k: string]: string | readonly JSONValue[] | {
8448
+ readonly [k: string]: JSONValue;
8449
+ } | null;
8450
+ };
8451
+ } & {
8452
+ instructions?: string | readonly JSONValue[] | {
8453
+ readonly [k: string]: JSONValue;
8454
+ };
8455
+ }> | Readonly<{
8456
+ form: "score";
8457
+ criteria: readonly (string | readonly JSONValue[] | {
8458
+ readonly [k: string]: JSONValue;
8459
+ } | null)[];
8460
+ } & {
8461
+ instructions?: string | readonly JSONValue[] | {
8462
+ readonly [k: string]: JSONValue;
8463
+ };
8464
+ }> | Readonly<{
8465
+ form: "noul";
8466
+ } & {
8467
+ instructions?: string | readonly JSONValue[] | {
8468
+ readonly [k: string]: JSONValue;
8469
+ };
8470
+ criteria?: Readonly<{} & {
8471
+ true?: string | readonly JSONValue[] | {
8472
+ readonly [k: string]: JSONValue;
8473
+ };
8474
+ false?: string | readonly JSONValue[] | {
8475
+ readonly [k: string]: JSONValue;
8476
+ };
8477
+ }>;
8478
+ }>;
8479
+ model: string;
8480
+ sources: readonly string[];
8481
+ state: string;
8482
+ time: number;
8483
+ answer: Readonly<{
8484
+ form: "choice";
8485
+ probabilities: {
8486
+ readonly [k: string]: number;
8487
+ };
8488
+ } & {}> | Readonly<{
8489
+ form: "score";
8490
+ probabilities: readonly number[];
8491
+ } & {}> | Readonly<{
8492
+ form: "noul";
8493
+ noul: number;
8494
+ } & {}>;
8495
+ } & {
8496
+ usage?: Readonly<{
8497
+ prompt: number;
8498
+ completion: number;
8499
+ total: number;
8500
+ } & {}>;
8501
+ }> | Readonly<{
8502
+ id: string;
8503
+ question: Readonly<{
8504
+ form: "choice";
8505
+ criteria: {
8506
+ readonly [k: string]: string | readonly JSONValue[] | {
8507
+ readonly [k: string]: JSONValue;
8508
+ } | null;
8509
+ };
8510
+ } & {
8511
+ instructions?: string | readonly JSONValue[] | {
8512
+ readonly [k: string]: JSONValue;
8513
+ };
8514
+ }> | Readonly<{
8515
+ form: "score";
8516
+ criteria: readonly (string | readonly JSONValue[] | {
8517
+ readonly [k: string]: JSONValue;
8518
+ } | null)[];
8519
+ } & {
8520
+ instructions?: string | readonly JSONValue[] | {
8521
+ readonly [k: string]: JSONValue;
8522
+ };
8523
+ }> | Readonly<{
8524
+ form: "noul";
8525
+ } & {
8526
+ instructions?: string | readonly JSONValue[] | {
8527
+ readonly [k: string]: JSONValue;
8528
+ };
8529
+ criteria?: Readonly<{} & {
8530
+ true?: string | readonly JSONValue[] | {
8531
+ readonly [k: string]: JSONValue;
8532
+ };
8533
+ false?: string | readonly JSONValue[] | {
8534
+ readonly [k: string]: JSONValue;
8535
+ };
8536
+ }>;
8537
+ }>;
8538
+ model: string;
8539
+ sources: readonly string[];
8540
+ state: string;
8541
+ time: number;
8542
+ refusal: Readonly<{
8543
+ missing: readonly string[];
8544
+ } & {}>;
8545
+ } & {
8546
+ usage?: Readonly<{
8547
+ prompt: number;
8548
+ completion: number;
8549
+ total: number;
8550
+ } & {}>;
8551
+ }>)[];
8552
+ }>;
8553
+ requests: readonly string[];
8554
+ notes: readonly string[];
8555
+ failures: readonly string[];
8556
+ } & {
8557
+ gauge?: Readonly<{
8558
+ scale: number;
8559
+ overhead: number;
8560
+ } & {}>;
8561
+ }>>;
8562
+
8563
+ /**
8564
+ * Describes a ledger snapshot exactly: an unknown key refuses, so a key a later version adds never reads
8565
+ * as absent.
8566
+ *
8567
+ * @remarks
8568
+ * `isLedgerSnapshot` is the door a hydrate reads, and this shape fills a refusal's faults. What the shape
8569
+ * cannot state, that each marked id names a message of the snapshot's own conversation, is the guard's
8570
+ * alone.
8571
+ */
8572
+ export declare const ledgerSnapshotShape: ObjectShape< {
8573
+ conversation: ObjectShape< {
8574
+ id: StringShape;
8575
+ sections: ArrayShape<ObjectShape< {
8576
+ id: StringShape;
8577
+ summary: StringShape;
8578
+ messages: ArrayShape<ObjectShape< {
8579
+ id: StringShape;
8580
+ role: LiteralShape<readonly ["system", "user", "assistant", "tool"]>;
8581
+ content: StringShape;
8582
+ calls: OptionalShape<ArrayShape<ObjectShape< {
8583
+ id: StringShape;
8584
+ name: StringShape;
8585
+ arguments: ObjectShape<Record<never, never>, JSONShape>;
8586
+ }, boolean | ContractShape>>>;
8587
+ call: OptionalShape<StringShape>;
8588
+ images: OptionalShape<ArrayShape<StringShape>>;
8589
+ thinking: OptionalShape<StringShape>;
8590
+ }, boolean | ContractShape>>;
8591
+ }, boolean | ContractShape>>;
8592
+ messages: ArrayShape<ObjectShape< {
8593
+ id: StringShape;
8594
+ role: LiteralShape<readonly ["system", "user", "assistant", "tool"]>;
8595
+ content: StringShape;
8596
+ calls: OptionalShape<ArrayShape<ObjectShape< {
8597
+ id: StringShape;
8598
+ name: StringShape;
8599
+ arguments: ObjectShape<Record<never, never>, JSONShape>;
8600
+ }, boolean | ContractShape>>>;
8601
+ call: OptionalShape<StringShape>;
8602
+ images: OptionalShape<ArrayShape<StringShape>>;
8603
+ thinking: OptionalShape<StringShape>;
8604
+ }, boolean | ContractShape>>;
8605
+ judgments: OptionalShape<ArrayShape<UnionShape<readonly [ObjectShape< {
8606
+ id: StringShape;
8607
+ question: UnionShape<readonly [ObjectShape< {
8608
+ form: LiteralShape<readonly ["choice"]>;
8609
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
8610
+ criteria: ObjectShape<Record<never, never>, NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
8611
+ }, boolean | ContractShape>, ObjectShape< {
8612
+ form: LiteralShape<readonly ["score"]>;
8613
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
8614
+ criteria: ArrayShape<NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
8615
+ }, boolean | ContractShape>, ObjectShape< {
8616
+ form: LiteralShape<readonly ["noul"]>;
8617
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
8618
+ criteria: OptionalShape<ObjectShape< {
8619
+ true: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
8620
+ false: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
8621
+ }, boolean | ContractShape>>;
8622
+ }, boolean | ContractShape>]>;
8623
+ model: StringShape;
8624
+ sources: ArrayShape<StringShape>;
8625
+ state: StringShape;
8626
+ time: NumberShape;
8627
+ usage: OptionalShape<ObjectShape< {
8628
+ prompt: NumberShape;
8629
+ completion: NumberShape;
8630
+ total: NumberShape;
8631
+ }, boolean | ContractShape>>;
8632
+ answer: UnionShape<readonly [ObjectShape< {
8633
+ form: LiteralShape<readonly ["choice"]>;
8634
+ probabilities: ObjectShape<Record<never, never>, NumberShape>;
8635
+ }, boolean | ContractShape>, ObjectShape< {
8636
+ form: LiteralShape<readonly ["score"]>;
8637
+ probabilities: ArrayShape<NumberShape>;
8638
+ }, boolean | ContractShape>, ObjectShape< {
8639
+ form: LiteralShape<readonly ["noul"]>;
8640
+ noul: NumberShape;
8641
+ }, boolean | ContractShape>]>;
8642
+ }, boolean | ContractShape>, ObjectShape< {
8643
+ id: StringShape;
8644
+ question: UnionShape<readonly [ObjectShape< {
8645
+ form: LiteralShape<readonly ["choice"]>;
8646
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
8647
+ criteria: ObjectShape<Record<never, never>, NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
8648
+ }, boolean | ContractShape>, ObjectShape< {
8649
+ form: LiteralShape<readonly ["score"]>;
8650
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
8651
+ criteria: ArrayShape<NullableShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>>;
8652
+ }, boolean | ContractShape>, ObjectShape< {
8653
+ form: LiteralShape<readonly ["noul"]>;
8654
+ instructions: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
8655
+ criteria: OptionalShape<ObjectShape< {
8656
+ true: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
8657
+ false: OptionalShape<UnionShape<readonly [StringShape, ArrayShape<JSONShape>, ObjectShape<Record<never, never>, JSONShape>]>>;
8658
+ }, boolean | ContractShape>>;
8659
+ }, boolean | ContractShape>]>;
8660
+ model: StringShape;
8661
+ sources: ArrayShape<StringShape>;
8662
+ state: StringShape;
8663
+ time: NumberShape;
8664
+ usage: OptionalShape<ObjectShape< {
8665
+ prompt: NumberShape;
8666
+ completion: NumberShape;
8667
+ total: NumberShape;
8668
+ }, boolean | ContractShape>>;
8669
+ refusal: ObjectShape< {
8670
+ missing: ArrayShape<StringShape>;
8671
+ }, boolean | ContractShape>;
8672
+ }, boolean | ContractShape>]>>>;
8673
+ }, boolean | ContractShape>;
8674
+ requests: ArrayShape<StringShape>;
8675
+ notes: ArrayShape<StringShape>;
8676
+ failures: ArrayShape<StringShape>;
8677
+ gauge: OptionalShape<ObjectShape< {
8678
+ scale: NumberShape;
8679
+ overhead: NumberShape;
8680
+ }, boolean | ContractShape>>;
8681
+ }, boolean | ContractShape>;
8682
+
7543
8683
  /**
7544
8684
  * Carries the probability cutoff of each reading the ledger takes from its judge.
7545
8685
  *
@@ -7821,6 +8961,21 @@ export declare interface Memo {
7821
8961
  */
7822
8962
  export declare const MEMO_SECTION_HEADER = "## Memos";
7823
8963
 
8964
+ /** Reads the faults of a refused memo revision. */
8965
+ export declare const memoContract: ContractInterface<Readonly<{
8966
+ id: string;
8967
+ name: string;
8968
+ description: string;
8969
+ content: string;
8970
+ time: number;
8971
+ } & {
8972
+ origin?: Readonly<{
8973
+ conversation: string;
8974
+ } & {
8975
+ message?: string;
8976
+ }>;
8977
+ }>>;
8978
+
7824
8979
  /**
7825
8980
  * Carries the data to author a {@link Memo} revision; the {@link MemoManagerInterface} that
7826
8981
  * stores it mints the `id` and records the `time`.
@@ -8154,6 +9309,19 @@ export declare class MemoryMemoStore implements MemoStoreInterface {
8154
9309
  delete(id: string): Promise<void>;
8155
9310
  }
8156
9311
 
9312
+ /** Describes a stored memo revision exactly. */
9313
+ export declare const memoShape: ObjectShape< {
9314
+ id: StringShape;
9315
+ name: StringShape;
9316
+ description: StringShape;
9317
+ content: StringShape;
9318
+ time: NumberShape;
9319
+ origin: OptionalShape<ObjectShape< {
9320
+ conversation: StringShape;
9321
+ message: OptionalShape<StringShape>;
9322
+ }, boolean | ContractShape>>;
9323
+ }, boolean | ContractShape>;
9324
+
8157
9325
  /**
8158
9326
  * Holds every revision of a memo set, oldest first; the current memo of a name is its last
8159
9327
  * revision.
@@ -8170,6 +9338,24 @@ export declare interface MemoSnapshot {
8170
9338
  readonly memos: readonly Memo[];
8171
9339
  }
8172
9340
 
9341
+ /** Reads the faults of a refused memo snapshot. */
9342
+ export declare const memoSnapshotContract: ContractInterface<Readonly<{
9343
+ id: string;
9344
+ memos: readonly Readonly<{
9345
+ id: string;
9346
+ name: string;
9347
+ description: string;
9348
+ content: string;
9349
+ time: number;
9350
+ } & {
9351
+ origin?: Readonly<{
9352
+ conversation: string;
9353
+ } & {
9354
+ message?: string;
9355
+ }>;
9356
+ }>[];
9357
+ } & {}>>;
9358
+
8173
9359
  /**
8174
9360
  * Represents one row of the table a {@link
8175
9361
  * import('./stores/DatabaseMemoStore.js').DatabaseMemoStore} persists — a memo set `id` plus its
@@ -8187,6 +9373,28 @@ export declare interface MemoSnapshotRow {
8187
9373
  readonly snapshot: unknown;
8188
9374
  }
8189
9375
 
9376
+ /**
9377
+ * Describes a stored memo set exactly: an unknown key refuses.
9378
+ *
9379
+ * @remarks
9380
+ * `isMemoSnapshot` is the door a hydrate and a store read, and this shape fills a refusal's faults. A
9381
+ * lockstep test holds that `is` implies the guard, and on the snapshot fixtures the converse.
9382
+ */
9383
+ export declare const memoSnapshotShape: ObjectShape< {
9384
+ id: StringShape;
9385
+ memos: ArrayShape<ObjectShape< {
9386
+ id: StringShape;
9387
+ name: StringShape;
9388
+ description: StringShape;
9389
+ content: StringShape;
9390
+ time: NumberShape;
9391
+ origin: OptionalShape<ObjectShape< {
9392
+ conversation: StringShape;
9393
+ message: OptionalShape<StringShape>;
9394
+ }, boolean | ContractShape>>;
9395
+ }, boolean | ContractShape>>;
9396
+ }, boolean | ContractShape>;
9397
+
8190
9398
  /**
8191
9399
  * Persists a {@link MemoSnapshot} by its memo set id — the async `get` / `set` / `delete`
8192
9400
  * primitives, holding no expiry, the memo twin of {@link
@@ -8330,6 +9538,45 @@ export declare interface MessageInput {
8330
9538
  readonly thinking?: string;
8331
9539
  }
8332
9540
 
9541
+ /** Reads the faults of a refused message input and validates a job's seed messages. */
9542
+ export declare const messageInputContract: ContractInterface<Readonly<{
9543
+ role: "assistant" | "system" | "tool" | "user";
9544
+ content: string;
9545
+ } & {
9546
+ calls?: readonly Readonly<{
9547
+ id: string;
9548
+ name: string;
9549
+ arguments: {
9550
+ readonly [k: string]: JSONValue;
9551
+ };
9552
+ } & {}>[];
9553
+ call?: string;
9554
+ images?: readonly string[];
9555
+ thinking?: string;
9556
+ }>>;
9557
+
9558
+ /**
9559
+ * Describes a message input's JSON projection: a {@link messageShape} with no `id`, which the
9560
+ * storing conversation mints.
9561
+ *
9562
+ * @remarks
9563
+ * A conversation's `add` checks a hoisted hand guard on every message and reads this shape's `audit`
9564
+ * only to fill a refusal's faults. A job's seed messages cross it at `build`. The role literal admits
9565
+ * `system`, so the conversation's `ROLE` refusal explains that case.
9566
+ */
9567
+ export declare const messageInputShape: ObjectShape< {
9568
+ role: LiteralShape<readonly ["system", "user", "assistant", "tool"]>;
9569
+ content: StringShape;
9570
+ calls: OptionalShape<ArrayShape<ObjectShape< {
9571
+ id: StringShape;
9572
+ name: StringShape;
9573
+ arguments: ObjectShape<Record<never, never>, JSONShape>;
9574
+ }, boolean | ContractShape>>>;
9575
+ call: OptionalShape<StringShape>;
9576
+ images: OptionalShape<ArrayShape<StringShape>>;
9577
+ thinking: OptionalShape<StringShape>;
9578
+ }, boolean | ContractShape>;
9579
+
8333
9580
  /**
8334
9581
  * Stores immutable {@link Message} records in insertion order and mints each `id` on `add` — the
8335
9582
  * message-store contract every {@link ConversationInterface} satisfies structurally, the
@@ -8576,7 +9823,7 @@ export declare type ProviderDelta = {
8576
9823
  *
8577
9824
  * @remarks
8578
9825
  * The provider base throws this error for a non-OK HTTP response, a missing response
8579
- * body, or a missing settled result when strict assembly is enabled, and with code `'PROTOCOL'`
9826
+ * body, a stream that ended with no settled result and no terminal record, a result or delta the published contract refuses, and with code `'PROTOCOL'`
8580
9827
  * when the framing seam's `parse` or `finish` throws anything but a provider error, with the throw
8581
9828
  * as `cause`. Concrete wire decoders also use it for malformed records and relayed provider
8582
9829
  * failures.
@@ -8587,6 +9834,8 @@ export declare class ProviderError extends Error {
8587
9834
  readonly code: ProviderErrorCode;
8588
9835
  /** Holds the response status for an HTTP failure, or undefined for other codes. */
8589
9836
  readonly status: number | undefined;
9837
+ /** Holds what the refusal found, such as its faults, or undefined when it carries none. */
9838
+ readonly context: Readonly<Record<string, unknown>> | undefined;
8590
9839
  constructor(code: ProviderErrorCode, message: string, options?: ProviderErrorOptions);
8591
9840
  }
8592
9841
 
@@ -8594,7 +9843,7 @@ export declare class ProviderError extends Error {
8594
9843
  export declare type ProviderErrorCode =
8595
9844
  /** Reports a non-OK HTTP response, including a relay request rejected with status 413. */
8596
9845
  'HTTP'
8597
- /** Reports a missing body, malformed wire record, or missing required settled result. */
9846
+ /** Reports a missing body, malformed wire record, a stream that ended with no settled result and no terminal record, or a result or delta the published contract refuses. */
8598
9847
  | 'PROTOCOL'
8599
9848
  /** Reports an upstream provider failure carried by a relay error record. */
8600
9849
  | 'PROVIDER';
@@ -8603,6 +9852,8 @@ export declare type ProviderErrorCode =
8603
9852
  export declare interface ProviderErrorOptions {
8604
9853
  readonly status?: number;
8605
9854
  readonly cause?: unknown;
9855
+ /** Holds the values that locate the failure, such as the `faults` of a refused question. */
9856
+ readonly context?: Readonly<Record<string, unknown>>;
8606
9857
  }
8607
9858
 
8608
9859
  /** Holds the decoded contribution of a wire record to a provider turn. */
@@ -8613,6 +9864,8 @@ export declare interface ProviderIncrement {
8613
9864
  readonly usage?: TokenUsage;
8614
9865
  readonly truncated?: boolean;
8615
9866
  readonly result?: ProviderResult;
9867
+ /** Marks the wire's terminal record, so a strict engine folds every increment into the settled result. */
9868
+ readonly done?: boolean;
8616
9869
  }
8617
9870
 
8618
9871
  /**
@@ -8989,6 +10242,41 @@ export declare function readChunks(body: ReadableStream<Uint8Array>, signal?: Ab
8989
10242
  */
8990
10243
  export declare function readFailure(response: Response, prefix: string, signal: AbortSignal): Promise<FailureRead>;
8991
10244
 
10245
+ /**
10246
+ * Reads what a judge result holds for one question, from its own keys alone.
10247
+ *
10248
+ * @param result - The reported answers and refusals
10249
+ * @param id - The question's id
10250
+ * @returns The answer and the refusal, each undefined when the result holds none
10251
+ * @example
10252
+ * ```ts
10253
+ * readJudgeOutcome({ model: 'm', answers: {} }, 'q') // { answer: undefined, refusal: undefined }
10254
+ * ```
10255
+ */
10256
+ export declare function readJudgeOutcome(result: JudgeResult, id: string): {
10257
+ readonly answer: JudgeAnswer | undefined;
10258
+ readonly refusal: Refusal | undefined;
10259
+ };
10260
+
10261
+ /**
10262
+ * Reads a foreign delta's two members once into an owned copy, the value a run checks and consumes.
10263
+ *
10264
+ * @remarks
10265
+ * A stream checks every delta, so this is a hand read rather than a record guard. Reading each member
10266
+ * once means a getter can't pass the check with one value and hand the run another. Unknown members
10267
+ * and a class instance pass, and an unreadable member reads as no delta.
10268
+ *
10269
+ * @param value - The value the stream yielded
10270
+ * @returns The owned delta, or undefined when the value is not one
10271
+ *
10272
+ * @example
10273
+ * ```ts
10274
+ * readProviderDelta({ channel: 'content', text: 'Hi' }) // { channel: 'content', text: 'Hi' }
10275
+ * readProviderDelta({ channel: 'audio', text: 'Hi' }) // undefined
10276
+ * ```
10277
+ */
10278
+ export declare function readProviderDelta(value: unknown): ProviderDelta | undefined;
10279
+
8992
10280
  /** Reports a question a wire could not read a candidate for; it lists the caller's keys and invents no probability. */
8993
10281
  export declare interface Refusal {
8994
10282
  readonly missing: readonly string[];
@@ -9581,26 +10869,27 @@ export declare function renderSection<T>(open: string, members: readonly T[], re
9581
10869
  export declare function renderStub(name: string, args: Readonly<Record<string, unknown>>, state: LedgerLookupState): string;
9582
10870
 
9583
10871
  /**
9584
- * Renders a tool's output as the string content of its tool message.
10872
+ * Renders a tool's output as the string content of its tool message, or returns `undefined` when JSON
10873
+ * cannot carry it.
9585
10874
  *
9586
10875
  * @remarks
9587
10876
  * A string passes through unchanged and `undefined` renders as `''`. Any other value renders as
9588
10877
  * its `JSON.stringify` text, byte for byte, when JSON can carry it. A value JSON cannot carry (a
9589
- * `BigInt`, a cycle, a symbol, a throwing `toJSON`) renders as `String(value)`, and as `''` when
9590
- * that conversion throws too, so a tool's output never rejects the run that dispatched it.
10878
+ * `BigInt`, a cycle, a symbol, a function, a throwing `toJSON`) returns `undefined`, which
10879
+ * {@link settleToolResult} turns into a tool failure.
9591
10880
  *
9592
10881
  * @param value - The tool's output (`ToolSuccess.value`, which may be `undefined`)
9593
- * @returns The message content
10882
+ * @returns The message content, or `undefined` when JSON cannot carry the value
9594
10883
  *
9595
10884
  * @example
9596
10885
  * ```ts
9597
10886
  * renderToolValue('sunny') // 'sunny'
9598
10887
  * renderToolValue({ count: 2 }) // '{"count":2}'
9599
10888
  * renderToolValue(undefined) // ''
9600
- * renderToolValue(10n) // '10'
10889
+ * renderToolValue(10n) // undefined
9601
10890
  * ```
9602
10891
  */
9603
- export declare function renderToolValue(value: unknown): string;
10892
+ export declare function renderToolValue(value: unknown): string | undefined;
9604
10893
 
9605
10894
  /**
9606
10895
  * Renders topic names as a comma-separated list in their supplied order.
@@ -9652,6 +10941,28 @@ export declare interface RequestMeasure {
9652
10941
  */
9653
10942
  export declare function requestToRelay(request: ProviderRequest): ProviderRequest;
9654
10943
 
10944
+ /**
10945
+ * Checks a run's final answer against its schema: the content must parse as JSON and satisfy the
10946
+ * schema, or the call throws a coded error carrying the faults.
10947
+ *
10948
+ * @remarks
10949
+ * The schema enters through the lenient `schemaToShape`, which widens every keyword it cannot express
10950
+ * and never narrows, because a provider constrains its own output and a false refusal would discard a
10951
+ * good answer. The check is `is`, because `explain` alone passes what `parse` would repair. Each call
10952
+ * compiles once, and a run has one final answer.
10953
+ *
10954
+ * @param content - The final answer's text
10955
+ * @param schema - The run's JSON Schema
10956
+ * @throws {AgentError} Thrown when the content is not JSON, misses the schema, or the schema does not compile (code `'SCHEMA'`), with the faults under `context.faults` for the first two
10957
+ *
10958
+ * @example
10959
+ * ```ts
10960
+ * requireAnswer('{"a":5}', { type: 'object', properties: { a: { type: 'number' } } })
10961
+ * requireAnswer('nope', { type: 'object' }) // throws AgentError ('SCHEMA')
10962
+ * ```
10963
+ */
10964
+ export declare function requireAnswer(content: string, schema: Readonly<Record<string, unknown>>): void;
10965
+
9655
10966
  /**
9656
10967
  * Returns a run's budget or allowance after checking it implements `BudgetInterface`, or throws a
9657
10968
  * coded error before the run starts it.
@@ -9700,28 +11011,29 @@ export declare function requireConversation(value: unknown): ConversationInterfa
9700
11011
  * throws a coded error.
9701
11012
  *
9702
11013
  * @remarks
9703
- * The check reads `id`, `sections`, `messages`, and `judgments` from `value` once each and builds
9704
- * a candidate from those reads: each array member becomes a fresh array holding the same element
9705
- * objects, and a member that is not an array stays as read, so the guard refuses it. The candidate
9706
- * must pass `isConversationSnapshot`, every section message and live message must play a
9707
- * `ConversationRole`, and no id may repeat across section ids, section message ids, and live
11014
+ * The check reads every own member of `value` once and builds a candidate from those reads: each
11015
+ * array member becomes a fresh array holding the same element objects, and a member that is not an
11016
+ * array stays as read, so the guard refuses it. The candidate must pass `isConversationSnapshot`, which
11017
+ * is exact, so an unknown key refuses rather than being dropped; every section message and live message
11018
+ * must play a `ConversationRole`; and no id may repeat across section ids, section message ids, and live
9708
11019
  * message ids. The `'ROLE'` refusal of a `system` message names the row a snapshot written before
9709
11020
  * 0.0.35 can hold, and each `'SNAPSHOT'` refusal asks for what `snapshot()` returned. The candidate
9710
11021
  * is returned, never `value`, so the check and the seating share one read. Element objects are kept
9711
11022
  * by reference, so a host is trusted not to edit a seated message object or to back its members
9712
- * with accessors.
11023
+ * with accessors. The contract's `audit` runs only after the guard refused, to fill `context.faults`.
9713
11024
  *
9714
11025
  * @param value - The snapshot to check, typically a stored read
9715
- * @returns The candidate snapshot, holding `id`, `sections`, `messages`, and `judgments` when present
9716
- * @throws ConversationError Thrown when the value fails `isConversationSnapshot` or repeats an id (code `'SNAPSHOT'`), or holds a message whose role is not a `ConversationRole` (code `'ROLE'`)
11026
+ * @param contract - The snapshot contract, whose `audit` is read only on a refusal
11027
+ * @returns The candidate snapshot
11028
+ * @throws ConversationError Thrown when the value fails `isConversationSnapshot` (code `'SNAPSHOT'`, its faults under `context.faults`), repeats an id (code `'SNAPSHOT'`), or holds a message whose role is not a `ConversationRole` (code `'ROLE'`)
9717
11029
  *
9718
11030
  * @example
9719
11031
  * ```ts
9720
- * requireConversationSnapshot({ id: 'c1', sections: [], messages: [] }) // { id: 'c1', sections: [], messages: [] }
9721
- * requireConversationSnapshot({ id: 'c1', sections: 'nope', messages: [] }) // throws ConversationError ('SNAPSHOT')
11032
+ * requireConversationSnapshot({ id: 'c1', sections: [], messages: [] }, conversationSnapshotContract) // { id: 'c1', sections: [], messages: [] }
11033
+ * requireConversationSnapshot({ id: 'c1', sections: 'nope', messages: [] }, conversationSnapshotContract) // throws ConversationError ('SNAPSHOT')
9722
11034
  * ```
9723
11035
  */
9724
- export declare function requireConversationSnapshot(value: unknown): ConversationSnapshot;
11036
+ export declare function requireConversationSnapshot(value: unknown, contract: Pick<ContractInterface<unknown>, 'audit' | 'schema'>): ConversationSnapshot;
9725
11037
 
9726
11038
  /**
9727
11039
  * Returns the cumulative switch after checking it does not combine with a `sections` cap, or throws a
@@ -9752,7 +11064,7 @@ export declare function requireCumulative(cumulative: boolean, cap: number | und
9752
11064
  * @param category - The registry category named in an error
9753
11065
  * @param name - The requested key
9754
11066
  * @returns The registered value
9755
- * @throws {AgentError} Thrown when the name is absent, with code REGISTRY and a `context` naming the `category` and the `name`.
11067
+ * @throws {AgentError} Thrown when the name is absent, with code REGISTRY, the name encoded and capped in its text because a tool refusal reaches a model, and a `context` naming the `category` and the `name`.
9756
11068
  * @example
9757
11069
  * ```ts
9758
11070
  * requireEntry(new Map([['main', provider]]), 'provider', 'main') // provider
@@ -9760,6 +11072,47 @@ export declare function requireCumulative(cumulative: boolean, cap: number | und
9760
11072
  */
9761
11073
  export declare function requireEntry<T>(pool: ReadonlyMap<string, T>, category: string, name: string): T;
9762
11074
 
11075
+ /**
11076
+ * Returns an authority's no-match decision after checking the options carry one, or throws a coded
11077
+ * error naming the two fallbacks a host chooses between.
11078
+ *
11079
+ * @remarks
11080
+ * A rules list says nothing about the calls it does not match, so no fallback is assumed: a denylist
11081
+ * and an allowlist differ only here. The check is {@link isAuthorityDecision}, a total guard, so a
11082
+ * missing options object and a malformed fallback refuse alike.
11083
+ *
11084
+ * @param options - The authority's options as a host passed them
11085
+ * @returns The fallback, narrowed to an {@link AuthorityDecision}
11086
+ * @throws {AgentError} Thrown when the options carry no valid `fallback` (code `'AUTHORITY'`)
11087
+ *
11088
+ * @example
11089
+ * ```ts
11090
+ * requireFallback({ fallback: { zone: 'default', verdict: 'deny' } }) // { zone: 'default', verdict: 'deny' }
11091
+ * ```
11092
+ */
11093
+ export declare function requireFallback(options: AuthorityOptions): AuthorityDecision;
11094
+
11095
+ /**
11096
+ * Returns after checking a complete judge result answered or refused every question it was asked, or
11097
+ * throws a coded error naming those it left out.
11098
+ *
11099
+ * @remarks
11100
+ * A cancelled call's partial is not complete, so `JudgmentManager` reads this on a settled result only,
11101
+ * and {@link buildJudgments} stores whatever a partial holds.
11102
+ *
11103
+ * An undefined value is no answer, as {@link buildJudgments} reads it, so a key alone doesn't count.
11104
+ *
11105
+ * @param request - The request whose question keys must be answered
11106
+ * @param result - The result the judge settled
11107
+ * @throws ConversationError Thrown when a question has neither an answer nor a refusal (code `'JUDGMENT'`), naming them under `context.questions`
11108
+ * @example
11109
+ * ```ts
11110
+ * requireJudgeResult({ state: 'text', questions: { a: { form: 'noul' } } }, { model: 'm', answers: {} })
11111
+ * // throws ConversationError ('JUDGMENT')
11112
+ * ```
11113
+ */
11114
+ export declare function requireJudgeResult(request: JudgeRequest, result: JudgeResult): void;
11115
+
9763
11116
  /**
9764
11117
  * Returns a stored judgment record after checking it, or throws a coded error.
9765
11118
  *
@@ -9801,26 +11154,67 @@ export declare function requireJudgment(value: unknown): Judgment;
9801
11154
  export declare function requireKeep(keep: number): number;
9802
11155
 
9803
11156
  /**
9804
- * Returns a tool-iteration cap after checking it is a nonnegative safe integer, or throws a coded
9805
- * error.
11157
+ * Returns a tool-iteration cap after checking it is a positive safe integer, or throws a coded error.
9806
11158
  *
9807
11159
  * @remarks
9808
- * The check is {@link import('../validators.js').isNonNegativeSafeInteger}, so `0` and `-0`
9809
- * pass while `NaN`, a fraction, a negative, and either infinity are refused. The error's `context`
9810
- * carries the refused value as `limit`.
11160
+ * The check is {@link import('../validators.js').isPositiveSafeInteger}, so `0`, `-0`, `NaN`, a
11161
+ * fraction, a negative, and either infinity are refused, because a run of no turns asks the provider
11162
+ * nothing and answers nothing. The error's `context` carries the refused value as `limit`.
9811
11163
  *
9812
11164
  * @param limit - The tool-iteration cap to check
9813
11165
  * @returns The cap unchanged
9814
- * @throws {AgentError} Thrown when `limit` is not a nonnegative safe integer (code `'LIMIT'`)
11166
+ * @throws {AgentError} Thrown when `limit` is not a positive safe integer (code `'LIMIT'`)
9815
11167
  *
9816
11168
  * @example
9817
11169
  * ```ts
9818
11170
  * requireLimit(3) // 3
9819
- * requireLimit(1.5) // throws AgentError ('LIMIT')
11171
+ * requireLimit(0) // throws AgentError ('LIMIT')
9820
11172
  * ```
9821
11173
  */
9822
11174
  export declare function requireLimit(limit: number): number;
9823
11175
 
11176
+ /**
11177
+ * Returns a message input after checking its role and its members, or throws a coded error.
11178
+ *
11179
+ * @remarks
11180
+ * The role goes first, through {@link requireRole}, so its refusal names what it received. The members
11181
+ * cross {@link isMessageInput}, and `audit` runs only after it refused, so a stored message costs one
11182
+ * guard read. Tool-call arguments must also be JSON values before a message is stored.
11183
+ *
11184
+ * @param input - The message input to check
11185
+ * @param contract - The message input contract, whose `audit` is read only on a refusal
11186
+ * @returns The input, narrowed
11187
+ * @throws ConversationError Thrown when the role is not a `ConversationRole` (code `'ROLE'`) or a member fails `isMessageInput` (code `'MESSAGE'`), with the faults under `context.faults`
11188
+ *
11189
+ * @example
11190
+ * ```ts
11191
+ * requireMessageInput({ role: 'user', content: 'hi' }, messageInputContract) // the input
11192
+ * requireMessageInput({ role: 'user' }, messageInputContract) // throws ConversationError ('MESSAGE')
11193
+ * ```
11194
+ */
11195
+ export declare function requireMessageInput(input: unknown, contract: Pick<ContractInterface<unknown>, 'audit' | 'schema'>): MessageInput;
11196
+
11197
+ /**
11198
+ * Owns a provider's settled result: reads each published member of the foreign value once into a fresh
11199
+ * record, checks that copy, and returns it, or throws a coded error the run rejects with.
11200
+ *
11201
+ * @remarks
11202
+ * The check is {@link isProviderResult}, so a class instance carrying the published members passes and
11203
+ * an unknown member is left behind. `usage` is copied count by count; `tools` keeps the array the
11204
+ * provider returned. An absent `usage` stays absent, which the loop bills as its estimate.
11205
+ *
11206
+ * @param value - The value a provider's stream returned
11207
+ * @returns The owned result
11208
+ * @throws {ProviderError} Thrown when the value does not carry the published members (code `PROTOCOL`)
11209
+ *
11210
+ * @example
11211
+ * ```ts
11212
+ * requireProviderResult({ content: 'answer', extra: true }) // { content: 'answer' }
11213
+ * requireProviderResult({}) // throws ProviderError ('PROTOCOL')
11214
+ * ```
11215
+ */
11216
+ export declare function requireProviderResult(value: unknown): ProviderResult;
11217
+
9824
11218
  /**
9825
11219
  * Returns a stored message role after checking it is a conversation role, or throws a coded error.
9826
11220
  *
@@ -9843,15 +11237,34 @@ export declare function requireLimit(limit: number): number;
9843
11237
  export declare function requireRole(role: unknown): ConversationRole;
9844
11238
 
9845
11239
  /**
9846
- * Returns a `sections` cap after checking its lower bound, or throws a coded error.
11240
+ * Returns an authority's rules after checking each one names a verdict, or throws a coded error naming
11241
+ * the first rule that does not.
11242
+ *
11243
+ * @remarks
11244
+ * Absent rules return an empty list. A rule's verdict decides a tool call, so a rule with none is
11245
+ * refused rather than read as an allow. The error's `context` carries the rule's index as `rule`.
11246
+ *
11247
+ * @param rules - The ordered rules, or `undefined` for none
11248
+ * @returns The rules unchanged, or an empty list when none were supplied
11249
+ * @throws {AgentError} Thrown when a rule has no valid `verdict` (code `'AUTHORITY'`)
11250
+ *
11251
+ * @example
11252
+ * ```ts
11253
+ * requireRules([{ match: () => true, zone: 'files', verdict: 'ask' }]).length // 1
11254
+ * ```
11255
+ */
11256
+ export declare function requireRules(rules: readonly AuthorityRule[] | undefined): readonly AuthorityRule[];
11257
+
11258
+ /**
11259
+ * Returns a `sections` cap after checking it is a positive safe integer, or throws a coded error.
9847
11260
  *
9848
11261
  * @remarks
9849
- * A supplied cap must satisfy `>= 1`; fractional caps and positive infinity pass, and `NaN`
9850
- * is refused. An absent cap leaves the sections list unbounded.
11262
+ * A fraction, positive infinity, and `NaN` are refused with `0` and a negative, because a count of
11263
+ * sections is a whole number. An absent cap leaves the sections list unbounded.
9851
11264
  *
9852
11265
  * @param cap - The cap to check, or `undefined` for no cap
9853
11266
  * @returns The cap unchanged, or `undefined` when none was supplied
9854
- * @throws ConversationError Thrown when the cap does not satisfy `>= 1` (code `'SECTIONS'`, including `NaN`)
11267
+ * @throws ConversationError Thrown when the cap is not a positive safe integer (code `'SECTIONS'`)
9855
11268
  *
9856
11269
  * @example
9857
11270
  * ```ts
@@ -9935,7 +11348,8 @@ export declare function sanitizeToken(value: number): number;
9935
11348
  /**
9936
11349
  * Sanitizes a {@link TokenUsage} into non-negative integers — the guard an agent's
9937
11350
  * abort-usage path applies to a provider's partial usage before it is charged against a
9938
- * budget or folded into the run total.
11351
+ * budget or folded into the run total, because a cancelled stream has no settled result to refuse;
11352
+ * a settled result's usage crosses the provider-result door instead.
9939
11353
  *
9940
11354
  * @remarks
9941
11355
  * Per field (`prompt` / `completion` / `total`): a non-finite value (`NaN`, `+Infinity`,
@@ -9965,6 +11379,39 @@ export declare function sanitizeUsage(usage: TokenUsage): TokenUsage;
9965
11379
  */
9966
11380
  export declare function scanAmendments(amendments: ReadonlyMap<string, readonly string[]>, start: string, admit: (id: string) => boolean): readonly string[];
9967
11381
 
11382
+ /**
11383
+ * Scans what a judge's answer must hold to its question: the same form, every probability in
11384
+ * `[0, 1]`, a choice's keys equal to the criteria keys, and a score as long as its levels.
11385
+ *
11386
+ * @remarks
11387
+ * These ties run where a judgment is written, at `JudgmentManager.add` and the `AgentJudge` result
11388
+ * ingestion. A read of a stored record checks only exact keys, literal forms, and number types,
11389
+ * because records written before the ties can miss them.
11390
+ *
11391
+ * @param question - The question that was asked
11392
+ * @param answer - The answer the judge gave
11393
+ * @returns Every broken tie as a fault, or an empty list
11394
+ * @example
11395
+ * ```ts
11396
+ * scanJudgmentTies({ form: 'noul' }, { form: 'noul', noul: 2 })
11397
+ * // [{ reason: 'constraint', path: ['answer', 'noul'], expected: 'number', constraint: 'max', limit: 1, received: '2' }]
11398
+ * ```
11399
+ */
11400
+ export declare function scanJudgmentTies(question: JudgeQuestion, answer: JudgeAnswer): readonly AuditFault[];
11401
+
11402
+ /**
11403
+ * Scans one probability against `[0, 1]`.
11404
+ *
11405
+ * @param value - The probability
11406
+ * @param path - Where it sits
11407
+ * @returns A constraint fault when it is out of bounds, or an empty list
11408
+ * @example
11409
+ * ```ts
11410
+ * scanProbability(0.5, ['answer', 'noul']) // []
11411
+ * ```
11412
+ */
11413
+ export declare function scanProbability(value: number | undefined, path: readonly string[]): readonly AuditFault[];
11414
+
9968
11415
  /**
9969
11416
  * Represents a named, immutable filter over a richer context's items — an optional allow-list per
9970
11417
  * category (`instructions` / `skills` / `memos` / `tools` / `files`), each keyed by that category's
@@ -10252,6 +11699,47 @@ export declare interface Section {
10252
11699
  readonly messages: readonly Message[];
10253
11700
  }
10254
11701
 
11702
+ /** Reads the faults of a refused section. */
11703
+ export declare const sectionContract: ContractInterface<Readonly<{
11704
+ id: string;
11705
+ summary: string;
11706
+ messages: readonly Readonly<{
11707
+ id: string;
11708
+ role: "assistant" | "system" | "tool" | "user";
11709
+ content: string;
11710
+ } & {
11711
+ calls?: readonly Readonly<{
11712
+ id: string;
11713
+ name: string;
11714
+ arguments: {
11715
+ readonly [k: string]: JSONValue;
11716
+ };
11717
+ } & {}>[];
11718
+ call?: string;
11719
+ images?: readonly string[];
11720
+ thinking?: string;
11721
+ }>[];
11722
+ } & {}>>;
11723
+
11724
+ /** Describes a compacted section: its id, its summary, and the originals it folded. */
11725
+ export declare const sectionShape: ObjectShape< {
11726
+ id: StringShape;
11727
+ summary: StringShape;
11728
+ messages: ArrayShape<ObjectShape< {
11729
+ id: StringShape;
11730
+ role: LiteralShape<readonly ["system", "user", "assistant", "tool"]>;
11731
+ content: StringShape;
11732
+ calls: OptionalShape<ArrayShape<ObjectShape< {
11733
+ id: StringShape;
11734
+ name: StringShape;
11735
+ arguments: ObjectShape<Record<never, never>, JSONShape>;
11736
+ }, boolean | ContractShape>>>;
11737
+ call: OptionalShape<StringShape>;
11738
+ images: OptionalShape<ArrayShape<StringShape>>;
11739
+ thinking: OptionalShape<StringShape>;
11740
+ }, boolean | ContractShape>>;
11741
+ }, boolean | ContractShape>;
11742
+
10255
11743
  /**
10256
11744
  * Carries the conversation part of the next prompt and the receipt for it.
10257
11745
  *
@@ -10352,6 +11840,29 @@ export declare function selectRecords(projection: LedgerProjection, request: Led
10352
11840
  */
10353
11841
  export declare function settleAgentJob(agent: AgentInterface, partial: boolean): Promise<AgentResult>;
10354
11842
 
11843
+ /**
11844
+ * Settles one dispatched result into the result the loop reports and the content of its tool message,
11845
+ * turning a success whose value JSON cannot carry into a tool failure the model reads.
11846
+ *
11847
+ * @remarks
11848
+ * A failure passes through with its `error` as the content. A success renders through
11849
+ * {@link renderToolValue}. A success that renders to `undefined` becomes the failure arm with the
11850
+ * call's `id` and `name`, whose `error` names the tool and the remedy.
11851
+ *
11852
+ * @param result - The result the tool manager returned for one call
11853
+ * @returns The result to report and the tool message content
11854
+ *
11855
+ * @example
11856
+ * ```ts
11857
+ * settleToolResult({ success: true, id: '1', name: 'read', value: { count: 2 } }).content // '{"count":2}'
11858
+ * settleToolResult({ success: true, id: '1', name: 'read', value: 10n }).outcome.success // false
11859
+ * ```
11860
+ */
11861
+ export declare function settleToolResult(result: ToolResult): {
11862
+ readonly outcome: ToolResult;
11863
+ readonly content: string;
11864
+ };
11865
+
10355
11866
  /**
10356
11867
  * Holds one skill: a name and a description the index shows, the instructions loading adds, and
10357
11868
  * bundled files.
@@ -10945,7 +12456,7 @@ export declare interface ThinkSplitterInterface {
10945
12456
  * counts, shared by the provider result and the agent frame wires.
10946
12457
  *
10947
12458
  * @remarks
10948
- * The guard refuses extra members; the contract parser drops them.
12459
+ * Each count is a nonnegative number. The guard refuses extra members; the contract parser drops them.
10949
12460
  */
10950
12461
  export declare const tokenUsageShape: ObjectShape< {
10951
12462
  prompt: NumberShape;
@@ -10955,9 +12466,9 @@ total: NumberShape;
10955
12466
 
10956
12467
  /**
10957
12468
  * Projects an unknown value onto a fresh, exact `TokenUsage` — capturing `prompt`, `completion`, and
10958
- * `total` once each through a total boundary, preserving finite negative and fractional counts,
10959
- * dropping extras, and resolving `undefined` for a non-object, a missing or non-finite count, a
10960
- * throwing getter, or a malformed or revoked proxy.
12469
+ * `total` once each through a total boundary, preserving fractional counts, dropping extras, and
12470
+ * resolving `undefined` for a non-object, a missing, negative, or non-finite count, a throwing getter,
12471
+ * or a malformed or revoked proxy.
10961
12472
  *
10962
12473
  * @remarks
10963
12474
  * The capture runs inside Contract's sanctioned exception boundary, so conforming accessors and
@@ -10966,13 +12477,14 @@ total: NumberShape;
10966
12477
  * before it projects, because this function refuses `undefined` like any other non-object.
10967
12478
  *
10968
12479
  * @param value - The unknown value to project
10969
- * @returns A fresh `{ prompt, completion, total }`, or `undefined` when the value is not a finite usage triple
12480
+ * @returns A fresh `{ prompt, completion, total }`, or `undefined` when the value is not a finite nonnegative usage triple
10970
12481
  *
10971
12482
  * @example
10972
12483
  * ```ts
10973
12484
  * import { tokenUsageToJSON } from '@orkestrel/agent'
10974
12485
  *
10975
- * tokenUsageToJSON({ prompt: 2, completion: -1, total: 1.5, cached: 4 }) // { prompt: 2, completion: -1, total: 1.5 }
12486
+ * tokenUsageToJSON({ prompt: 2, completion: 1, total: 1.5, cached: 4 }) // { prompt: 2, completion: 1, total: 1.5 }
12487
+ * tokenUsageToJSON({ prompt: 2, completion: -1, total: 1 }) // undefined
10976
12488
  * tokenUsageToJSON({ prompt: 2, completion: Infinity, total: 3 }) // undefined
10977
12489
  * ```
10978
12490
  */