@orkestrel/agent 0.0.31 → 0.0.32

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.
@@ -8,7 +8,7 @@ import { WorkspaceManager, isBinary, isText } from "@orkestrel/workspace";
8
8
  import { createQueue } from "@orkestrel/queue";
9
9
  import { createRunner, errorToMessage } from "@orkestrel/workflow";
10
10
  import { createAbort } from "@orkestrel/abort";
11
- //#region src/core/constants.ts
11
+ // src/core/constants.ts
12
12
  /**
13
13
  * Lists the roles a conversation message can play, in the order the wire contract names them —
14
14
  * the one list the {@link import('./types.js').MessageRole} union derives from, the message
@@ -20,8 +20,7 @@ var MESSAGE_ROLES = Object.freeze([
20
20
  "assistant",
21
21
  "tool"
22
22
  ]);
23
- //#endregion
24
- //#region src/core/errors.ts
23
+ // src/core/errors.ts
25
24
  /**
26
25
  * Reports a judge call cancelled by the caller's signal or its deadline, carrying the
27
26
  * {@link JudgeResult} merged from the calls that completed before the cancel and the
@@ -57,8 +56,7 @@ var JudgeAbortError = class extends Error {
57
56
  function isJudgeAbortError(value) {
58
57
  return isInstance(value, JudgeAbortError);
59
58
  }
60
- //#endregion
61
- //#region src/core/shapers.ts
59
+ // src/core/shapers.ts
62
60
  /**
63
61
  * Describes a tool call's JSON wire projection.
64
62
  *
@@ -88,12 +86,10 @@ var messageShape = objectShape({
88
86
  images: optionalShape(arrayShape(stringShape())),
89
87
  thinking: optionalShape(stringShape())
90
88
  });
91
- //#endregion
92
- //#region src/core/contracts.ts
89
+ // src/core/contracts.ts
93
90
  /** Validates and projects conversation messages at a JSON wire boundary. */
94
91
  var messageContract = createContract(messageShape);
95
- //#endregion
96
- //#region src/core/cloners.ts
92
+ // src/core/cloners.ts
97
93
  /**
98
94
  * Owns a value by serializing it to JSON and parsing the text, so the copy shares nothing with its source.
99
95
  *
@@ -115,8 +111,7 @@ function copyJSON(value) {
115
111
  if (!text.success || typeof text.value !== "string") return void 0;
116
112
  return parseJSON(text.value);
117
113
  }
118
- //#endregion
119
- //#region src/core/helpers.ts
114
+ // src/core/helpers.ts
120
115
  /**
121
116
  * Filters a list of members by a {@link import('./contexts/index.js').ScopeInterface} allow-list of keys —
122
117
  * `undefined` passes everything, `[]` passes nothing, and a non-empty list passes the listed keys
@@ -455,8 +450,7 @@ function renderJSON(value) {
455
450
  function matchesJudgment(judgment, question, sources, state, model) {
456
451
  return judgment.model === model && judgment.state === state && judgment.sources.length === sources.length && judgment.sources.every((id, index) => id === sources[index]) && JSON.stringify(judgment.question) === JSON.stringify(question);
457
452
  }
458
- //#endregion
459
- //#region src/core/validators.ts
453
+ // src/core/validators.ts
460
454
  /**
461
455
  * Checks whether a value is a judge entry: a string, a JSON record, or a JSON array.
462
456
  *
@@ -533,8 +527,7 @@ function isJudgeQuestion(value) {
533
527
  function isNonNegativeSafeInteger(value) {
534
528
  return isFiniteNumber(value) && Number.isSafeInteger(value) && value >= 0;
535
529
  }
536
- //#endregion
537
- //#region src/core/providers/constants.ts
530
+ // src/core/providers/constants.ts
538
531
  /**
539
532
  * Names the opening tag a {@link import('./ThinkSplitter.js').ThinkSplitter} recognizes as the start of
540
533
  * an in-content reasoning span — `'<think>'`, the de-facto wire convention thinking models
@@ -600,8 +593,7 @@ var INVALID_RELAY_STATUS = 400;
600
593
  var OVERSIZED_RELAY_STATUS = 413;
601
594
  /** Names the System One decision endpoint shared by compatible servers. */
602
595
  var SYSTEM_ONE_PATH = "/v1/systemone";
603
- //#endregion
604
- //#region src/core/providers/errors.ts
596
+ // src/core/providers/errors.ts
605
597
  /**
606
598
  * Reports a provider stream cancelled mid-flight by its bound signal — thrown by the
607
599
  * `stream` method of a {@link ProviderInterface}, carrying the {@link ProviderResult} assembled from
@@ -712,8 +704,7 @@ var JudgeError = class extends Error {
712
704
  function isJudgeError(value) {
713
705
  return isInstance(value, JudgeError);
714
706
  }
715
- //#endregion
716
- //#region src/core/providers/shapers.ts
707
+ // src/core/providers/shapers.ts
717
708
  /**
718
709
  * Describes a provider request's JSON wire projection.
719
710
  *
@@ -773,16 +764,14 @@ var relayFrameShape = unionShape(objectShape({
773
764
  channel: literalShape(["error"]),
774
765
  message: stringShape()
775
766
  }));
776
- //#endregion
777
- //#region src/core/providers/contracts.ts
767
+ // src/core/providers/contracts.ts
778
768
  /** Validates and projects provider requests at a JSON wire boundary. */
779
769
  var providerRequestContract = createContract(providerRequestShape);
780
770
  /** Validates and projects provider results at a JSON wire boundary. */
781
771
  var providerResultContract = createContract(providerResultShape);
782
772
  /** Validates and projects channel-discriminated relay frames at a JSON wire boundary. */
783
773
  var relayFrameContract = createContract(relayFrameShape);
784
- //#endregion
785
- //#region src/core/providers/helpers.ts
774
+ // src/core/providers/helpers.ts
786
775
  /**
787
776
  * Assembles a provider result with only populated optional fields.
788
777
  *
@@ -1263,8 +1252,7 @@ function extractSystemOneUsage(usage) {
1263
1252
  });
1264
1253
  return extracted.success ? extracted.value : void 0;
1265
1254
  }
1266
- //#endregion
1267
- //#region src/core/providers/RelayStream.ts
1255
+ // src/core/providers/RelayStream.ts
1268
1256
  /**
1269
1257
  * Streams a provider call as validated NDJSON frames under response backpressure.
1270
1258
  *
@@ -1372,8 +1360,7 @@ var RelayStream = class {
1372
1360
  this.#signal.removeEventListener("abort", this.#listener);
1373
1361
  }
1374
1362
  };
1375
- //#endregion
1376
- //#region src/core/providers/ThinkSplitter.ts
1363
+ // src/core/providers/ThinkSplitter.ts
1377
1364
  /**
1378
1365
  * Separates `<think>…</think>` spans from raw content deltas with per-stream state: text inside a
1379
1366
  * span accumulates on `thinking`, and text outside it returns as clean content, so a provider
@@ -1491,8 +1478,7 @@ var ThinkSplitter = class {
1491
1478
  return Array.from({ length: max }, (_, index) => max - index).find((length) => this.#pending.endsWith(tag.slice(0, length))) ?? 0;
1492
1479
  }
1493
1480
  };
1494
- //#endregion
1495
- //#region src/core/providers/AgentProvider.ts
1481
+ // src/core/providers/AgentProvider.ts
1496
1482
  /**
1497
1483
  * Implements bounded HTTP streaming and result assembly behind concrete wire seams.
1498
1484
  *
@@ -1703,8 +1689,7 @@ var AgentProvider = class {
1703
1689
  return response;
1704
1690
  }
1705
1691
  };
1706
- //#endregion
1707
- //#region src/core/providers/RelayProvider.ts
1692
+ // src/core/providers/RelayProvider.ts
1708
1693
  /**
1709
1694
  * Carries provider calls over an authenticated NDJSON relay endpoint.
1710
1695
  *
@@ -1821,8 +1806,7 @@ var RelayProvider = class extends AgentProvider {
1821
1806
  return parser.parse("\n");
1822
1807
  }
1823
1808
  };
1824
- //#endregion
1825
- //#region src/core/providers/AgentJudge.ts
1809
+ // src/core/providers/AgentJudge.ts
1826
1810
  /**
1827
1811
  * Implements the bounded HTTP calls, validation, and result merging of a judge behind concrete
1828
1812
  * wire seams.
@@ -1962,8 +1946,7 @@ var AgentJudge = class {
1962
1946
  }
1963
1947
  }
1964
1948
  };
1965
- //#endregion
1966
- //#region src/core/providers/validators.ts
1949
+ // src/core/providers/validators.ts
1967
1950
  /**
1968
1951
  * Checks whether a value is a System One response envelope with optional model and usage.
1969
1952
  *
@@ -2021,8 +2004,7 @@ function isSystemOneAnswer(value) {
2021
2004
  });
2022
2005
  return checked.success && checked.value;
2023
2006
  }
2024
- //#endregion
2025
- //#region src/core/providers/SystemOneJudge.ts
2007
+ // src/core/providers/SystemOneJudge.ts
2026
2008
  /**
2027
2009
  * Carries judge questions over the System One protocol and derives answers from server distributions.
2028
2010
  *
@@ -2123,8 +2105,7 @@ var SystemOneJudge = class extends AgentJudge {
2123
2105
  };
2124
2106
  }
2125
2107
  };
2126
- //#endregion
2127
- //#region src/core/providers/factories.ts
2108
+ // src/core/providers/factories.ts
2128
2109
  /**
2129
2110
  * Creates an authorized relay handler that validates a bounded JSON request before streaming.
2130
2111
  *
@@ -2283,8 +2264,7 @@ function createThinkSplitter() {
2283
2264
  function createSystemOneJudge(options) {
2284
2265
  return new SystemOneJudge(options);
2285
2266
  }
2286
- //#endregion
2287
- //#region src/core/conversations/constants.ts
2267
+ // src/core/conversations/constants.ts
2288
2268
  /**
2289
2269
  * Sets the default number of recent live messages the `compact()` method of a
2290
2270
  * {@link ConversationInterface} retains verbatim — `0`, so a manual `compact()` keeps no recent tail and folds every
@@ -2311,8 +2291,7 @@ var DEFAULT_CONVERSATION_KEEP = 0;
2311
2291
  * because it interpolates the per-call provenance `label`).
2312
2292
  */
2313
2293
  var CONVERSATION_RECAP_PREFIX = "[Summary of earlier messages] ";
2314
- //#endregion
2315
- //#region src/core/conversations/errors.ts
2294
+ // src/core/conversations/errors.ts
2316
2295
  /**
2317
2296
  * Reports a conversation with no {@link ConversationSummaryHandler} to fold its messages with, a
2318
2297
  * `sections` cap below `1`, a `keep` that is not a nonnegative safe integer, or a judgment or
@@ -2372,8 +2351,7 @@ var ConversationError = class extends Error {
2372
2351
  function isConversationError(value) {
2373
2352
  return isInstance(value, ConversationError);
2374
2353
  }
2375
- //#endregion
2376
- //#region src/core/conversations/validators.ts
2354
+ // src/core/conversations/validators.ts
2377
2355
  /**
2378
2356
  * Checks whether a value satisfies the domain conversation-message contract.
2379
2357
  *
@@ -2515,8 +2493,7 @@ function isConversationSnapshot(value) {
2515
2493
  judgments: optionalOf(arrayOf(isJudgment))
2516
2494
  }, ["judgments"])(value);
2517
2495
  }
2518
- //#endregion
2519
- //#region src/core/conversations/helpers.ts
2496
+ // src/core/conversations/helpers.ts
2520
2497
  /**
2521
2498
  * Builds records for answered or refused request keys, attaching usage only for a single question.
2522
2499
  *
@@ -2725,8 +2702,7 @@ function raceSignal(promise, signal) {
2725
2702
  promise.then(resolve, reject).finally(() => settled.abort());
2726
2703
  });
2727
2704
  }
2728
- //#endregion
2729
- //#region src/core/conversations/JudgmentManager.ts
2705
+ // src/core/conversations/JudgmentManager.ts
2730
2706
  /**
2731
2707
  * Stores judgments in insertion order and asks a judge only for unmatched question identities.
2732
2708
  *
@@ -2822,8 +2798,7 @@ var JudgmentManager = class {
2822
2798
  return structuredClone(judgment);
2823
2799
  }
2824
2800
  };
2825
- //#endregion
2826
- //#region src/core/conversations/Conversation.ts
2801
+ // src/core/conversations/Conversation.ts
2827
2802
  /**
2828
2803
  * Represents a conversation — a live uncompacted tail of messages it owns directly above a flat
2829
2804
  * message store, plus compacted, summarized {@link Section} records and a `summarizable` flag,
@@ -3041,8 +3016,7 @@ var Conversation = class {
3041
3016
  return message;
3042
3017
  }
3043
3018
  };
3044
- //#endregion
3045
- //#region src/core/conversations/ConversationManager.ts
3019
+ // src/core/conversations/ConversationManager.ts
3046
3020
  /**
3047
3021
  * Registers {@link Conversation} instances keyed by `id`, in insertion order, with an active pointer —
3048
3022
  * the id-keyed store over the conversation layer, the `active` / `switch` seam the
@@ -3164,8 +3138,7 @@ var ConversationManager = class {
3164
3138
  return removed;
3165
3139
  }
3166
3140
  };
3167
- //#endregion
3168
- //#region src/core/conversations/stores/MemoryConversationStore.ts
3141
+ // src/core/conversations/stores/MemoryConversationStore.ts
3169
3142
  /**
3170
3143
  * Implements the {@link ConversationStoreInterface} in memory — a process-lifetime `Map` of
3171
3144
  * {@link ConversationSnapshot} records keyed by conversation id, the default store
@@ -3238,8 +3211,7 @@ var MemoryConversationStore = class {
3238
3211
  return Promise.resolve();
3239
3212
  }
3240
3213
  };
3241
- //#endregion
3242
- //#region src/core/conversations/stores/DatabaseConversationStore.ts
3214
+ // src/core/conversations/stores/DatabaseConversationStore.ts
3243
3215
  /**
3244
3216
  * Backs a {@link ConversationStoreInterface} with one table of the `databases` layer — a
3245
3217
  * conversation's durable state is a row holding the snapshot as one opaque JSON column, narrowed
@@ -3346,8 +3318,7 @@ var DatabaseConversationStore = class {
3346
3318
  await this.#table.remove(id);
3347
3319
  }
3348
3320
  };
3349
- //#endregion
3350
- //#region src/core/conversations/factories.ts
3321
+ // src/core/conversations/factories.ts
3351
3322
  /**
3352
3323
  * Creates a conversation — a {@link ConversationInterface} grouping messages above a flat
3353
3324
  * message store it owns directly, with compaction into summarized sections, on-demand
@@ -3522,8 +3493,7 @@ function createDatabaseConversationStore(driver = createMemoryDriver()) {
3522
3493
  tables: { conversations: columns }
3523
3494
  }).table("conversations"));
3524
3495
  }
3525
- //#endregion
3526
- //#region src/core/contexts/constants.ts
3496
+ // src/core/contexts/constants.ts
3527
3497
  /**
3528
3498
  * Names the section header the `build()` method of {@link import('./AgentContext.js').AgentContext}
3529
3499
  * renders the active workspace's text files under — `'## Workspace'`, the leading line of the dedicated
@@ -3539,8 +3509,7 @@ function createDatabaseConversationStore(driver = createMemoryDriver()) {
3539
3509
  * `base64` payload attaches to the last user message.
3540
3510
  */
3541
3511
  var WORKSPACE_SECTION_HEADER = "## Workspace";
3542
- //#endregion
3543
- //#region src/core/contexts/instructions/Instruction.ts
3512
+ // src/core/contexts/instructions/Instruction.ts
3544
3513
  /**
3545
3514
  * Represents an immutable named directive — an {@link InstructionInterface} assembled once from
3546
3515
  * its input (`name` / `content` and an optional `priority`), the `id` minted at
@@ -3575,8 +3544,7 @@ var Instruction = class {
3575
3544
  if (input.override !== void 0) this.override = input.override;
3576
3545
  }
3577
3546
  };
3578
- //#endregion
3579
- //#region src/core/contexts/instructions/InstructionManager.ts
3547
+ // src/core/contexts/instructions/InstructionManager.ts
3580
3548
  /**
3581
3549
  * Registers the immutable {@link Instruction} instances a richer context assembles a directives block
3582
3550
  * from — keyed by `name` so adding an instruction whose name is already stored overwrites it,
@@ -3667,8 +3635,7 @@ var InstructionManager = class {
3667
3635
  return removed;
3668
3636
  }
3669
3637
  };
3670
- //#endregion
3671
- //#region src/core/contexts/helpers.ts
3638
+ // src/core/contexts/helpers.ts
3672
3639
  /**
3673
3640
  * Renders a path-addressed text body as a fenced reference block — a `File: <path>` label line
3674
3641
  * over a language-tagged fence, the framing the
@@ -3839,8 +3806,7 @@ function intersectKeys(parent, child) {
3839
3806
  const allowed = new Set(parent);
3840
3807
  return child.filter((key) => allowed.has(key));
3841
3808
  }
3842
- //#endregion
3843
- //#region src/core/contexts/scopes/Scope.ts
3809
+ // src/core/contexts/scopes/Scope.ts
3844
3810
  /**
3845
3811
  * Represents a named, immutable filter over a richer context's items — an optional allow-list per
3846
3812
  * category (`instructions` / `tools` / `files`), each keyed by that category's identity (an
@@ -3900,8 +3866,7 @@ var Scope = class Scope {
3900
3866
  });
3901
3867
  }
3902
3868
  };
3903
- //#endregion
3904
- //#region src/core/contexts/scopes/ScopeManager.ts
3869
+ // src/core/contexts/scopes/ScopeManager.ts
3905
3870
  /**
3906
3871
  * Registers the named filters a richer context reuses — immutable {@link Scope} instances keyed by their
3907
3872
  * minted `id`, in insertion order, where `add` always mints and stores rather than overwriting,
@@ -3968,8 +3933,7 @@ var ScopeManager = class {
3968
3933
  return removed;
3969
3934
  }
3970
3935
  };
3971
- //#endregion
3972
- //#region src/core/contexts/AgentContext.ts
3936
+ // src/core/contexts/AgentContext.ts
3973
3937
  /**
3974
3938
  * Assembles a provider request from the richer turn context — the optional system prompt, the
3975
3939
  * observable context managers (instructions / workspaces), the
@@ -4123,8 +4087,7 @@ var AgentContext = class {
4123
4087
  return this.#conversations.active ?? conversation;
4124
4088
  }
4125
4089
  };
4126
- //#endregion
4127
- //#region src/core/contexts/factories.ts
4090
+ // src/core/contexts/factories.ts
4128
4091
  /**
4129
4092
  * Creates an instruction — an immutable {@link InstructionInterface} (a named directive)
4130
4093
  * from its `name` / `content` and optional `priority`, the `id` minted at construction.
@@ -4268,8 +4231,7 @@ function createScopeManager(options) {
4268
4231
  function createAgentContext(options) {
4269
4232
  return new AgentContext(options);
4270
4233
  }
4271
- //#endregion
4272
- //#region src/core/agents/constants.ts
4234
+ // src/core/agents/constants.ts
4273
4235
  /**
4274
4236
  * Caps an {@link AgentInterface} turn's tool iterations by default — `10` context → provider →
4275
4237
  * tools cycles before the loop stops, so a model that keeps requesting tools can never loop
@@ -4296,8 +4258,7 @@ var MESSAGE_TOKEN_OVERHEAD = 4;
4296
4258
  * exact count.
4297
4259
  */
4298
4260
  var IMAGE_TOKEN_ESTIMATE = 512;
4299
- //#endregion
4300
- //#region src/core/agents/errors.ts
4261
+ // src/core/agents/errors.ts
4301
4262
  /**
4302
4263
  * Reports an {@link AgentInterface} run that ended {@link AgentResult.partial} under a
4303
4264
  * `partial` policy of `false` (the default) — thrown by an agent-job handler (a
@@ -4402,8 +4363,7 @@ var AgentError = class extends Error {
4402
4363
  function isAgentError(value) {
4403
4364
  return isInstance(value, AgentError);
4404
4365
  }
4405
- //#endregion
4406
- //#region src/core/agents/Channel.ts
4366
+ // src/core/agents/Channel.ts
4407
4367
  /**
4408
4368
  * Buffers chunks in a minimal unbounded async channel — the eager pump writes them in (`push`)
4409
4369
  * and ends it (`close` / `fail`) regardless of consumption, while a consumer reads them back live
@@ -4473,8 +4433,7 @@ var Channel = class {
4473
4433
  });
4474
4434
  }
4475
4435
  };
4476
- //#endregion
4477
- //#region src/core/agents/helpers.ts
4436
+ // src/core/agents/helpers.ts
4478
4437
  /**
4479
4438
  * Projects an unknown value onto a fresh, exact `JSONValue` representation of an
4480
4439
  * {@link AgentResult} — capturing each structural field once through a total boundary,
@@ -5056,8 +5015,7 @@ function extractQueueOptions(options) {
5056
5015
  ...timeout === void 0 ? {} : { timeout }
5057
5016
  };
5058
5017
  }
5059
- //#endregion
5060
- //#region src/core/agents/Agent.ts
5018
+ // src/core/agents/Agent.ts
5061
5019
  /**
5062
5020
  * Composes a {@link ProviderInterface}, an {@link AgentContext}, and a
5063
5021
  * {@link ToolManagerInterface} into a bounded context → provider → tools → repeat turn, exposed
@@ -5620,8 +5578,7 @@ var Agent = class {
5620
5578
  return AbortSignal.any(signals);
5621
5579
  }
5622
5580
  };
5623
- //#endregion
5624
- //#region src/core/agents/AgentFanout.ts
5581
+ // src/core/agents/AgentFanout.ts
5625
5582
  /**
5626
5583
  * Executes one runner's agent jobs — spawning each unit's declared children on its first attempt
5627
5584
  * only, then rehydrating the unit through a registry with the controller signal and settling it
@@ -5679,8 +5636,7 @@ var AgentFanout = class {
5679
5636
  return settleAgentJob(this.#registry.build(controller.input, controller.signal), this.#partial);
5680
5637
  }
5681
5638
  };
5682
- //#endregion
5683
- //#region src/core/agents/Authority.ts
5639
+ // src/core/agents/Authority.ts
5684
5640
  /**
5685
5641
  * Gates the agent loop's tool calls — the synchronous policy consulted before each call runs,
5686
5642
  * turning one {@link AuthorityContext} into an {@link AuthorityDecision} by walking the ordered
@@ -5734,8 +5690,7 @@ var Authority = class {
5734
5690
  return this.#fallback;
5735
5691
  }
5736
5692
  };
5737
- //#endregion
5738
- //#region src/core/agents/AgentRegistry.ts
5693
+ // src/core/agents/AgentRegistry.ts
5739
5694
  /**
5740
5695
  * Makes a durable, JSON-serializable {@link AgentJobInput} runnable — holds the named pools of
5741
5696
  * live, non-serializable pieces (providers, tools, authorities, schedulers), throws on a name
@@ -5822,8 +5777,7 @@ var AgentRegistry = class {
5822
5777
  return manager;
5823
5778
  }
5824
5779
  };
5825
- //#endregion
5826
- //#region src/core/agents/factories.ts
5780
+ // src/core/agents/factories.ts
5827
5781
  /**
5828
5782
  * Creates an agent loop — an {@link AgentInterface} composing a
5829
5783
  * {@link ProviderInterface}, its {@link AgentContextInterface}, and a tool registry
@@ -6058,8 +6012,7 @@ function createAgentRunner(options) {
6058
6012
  handler: fanout.execute.bind(fanout)
6059
6013
  });
6060
6014
  }
6061
- //#endregion
6062
- //#region src/core/ledgers/constants.ts
6015
+ // src/core/ledgers/constants.ts
6063
6016
  /**
6064
6017
  * Lists the categories the ledger files a message under, in the order the category question
6065
6018
  * names them — the one list the {@link LedgerCategory} union derives from.
@@ -6162,8 +6115,7 @@ var DEFAULT_RECALL_LIMIT = 2;
6162
6115
  var LEDGER_SCALE_DRIFT = .06;
6163
6116
  /** Matches the logprob decoding failure `invalid or duplicate top logprob token`, which the ledger holds for the ledger's life. */
6164
6117
  var DETERMINISTIC_JUDGE_ERROR = /invalid or duplicate top logprob token/;
6165
- //#endregion
6166
- //#region src/core/ledgers/errors.ts
6118
+ // src/core/ledgers/errors.ts
6167
6119
  /**
6168
6120
  * Reports an invalid ledger configuration, failed calibration, or unowned request selection,
6169
6121
  * carrying the machine-readable `code`.
@@ -6205,15 +6157,14 @@ var LedgerError = class extends Error {
6205
6157
  function isLedgerError(value) {
6206
6158
  return isInstance(value, LedgerError);
6207
6159
  }
6208
- //#endregion
6209
- //#region src/core/ledgers/helpers.ts
6160
+ // src/core/ledgers/helpers.ts
6210
6161
  /**
6211
6162
  * Collects the live message ids placed in records or left without a record.
6212
6163
  * @param projection - The projected records and unplaced ids
6213
6164
  * @returns The distinct live message ids
6214
6165
  * @example
6215
6166
  * ```ts
6216
- * collectProjectionIds({ records: [], stale: [], orphans: ['message-1'] }) // Set { 'message-1' }
6167
+ * collectProjectionIds({ records: [], amendments: [], orphans: ['message-1'] }) // Set { 'message-1' }
6217
6168
  * ```
6218
6169
  */
6219
6170
  function collectProjectionIds(projection) {
@@ -6652,8 +6603,8 @@ function matchEntities(registry, text, partial) {
6652
6603
  * argument. A message that names no owner joins where its earlier side of an amendment pair joins,
6653
6604
  * or on the rules record when it is filed as a rule or a correction, and is an orphan otherwise.
6654
6605
  *
6655
- * A sentence an amending message made stale is left out and listed in `stale`. An amending message
6656
- * that is itself replaced keeps that effect, so the old value never revives.
6606
+ * Every live sentence is retained. Accepted direct edges are listed in `amendments`. An amending message
6607
+ * that is itself superseded retains its accepted edge without restoring its text.
6657
6608
  *
6658
6609
  * A sentence that opens with a pronoun takes the party named in the sentence before it. The reading
6659
6610
  * trusts capitals, so a capitalized word that is no person, such as a carrier named mid-sentence,
@@ -6661,7 +6612,7 @@ function matchEntities(registry, text, partial) {
6661
6612
  * the follow-up facts the records exist for.
6662
6613
  *
6663
6614
  * @param input - The messages, readings, entities, and classification to project
6664
- * @returns The records with owner records ordered by their first member and the rules record last, the stale sentences, and the live message ids no record placed
6615
+ * @returns The records with owner records ordered by their first member and the rules record last, the accepted amendments, and the live message ids no record placed
6665
6616
  *
6666
6617
  * @example
6667
6618
  * ```ts
@@ -6686,8 +6637,7 @@ function buildRecords(input) {
6686
6637
  earlier,
6687
6638
  later
6688
6639
  }))), (pair) => pair.later)].map(([later, pairs]) => [later, pairs.map((pair) => pair.earlier)]));
6689
- const stale = collectStale(input, byId, live);
6690
- const dead = new Set(stale.map((entry) => `${entry.source} ${entry.sentence}`));
6640
+ const amendments = collectAmendments(input, byId, live);
6691
6641
  const holders = [...input.owners.values()].flat();
6692
6642
  const system = collectNames(input.system);
6693
6643
  const settled = /* @__PURE__ */ new Map();
@@ -6702,7 +6652,7 @@ function buildRecords(input) {
6702
6652
  id
6703
6653
  }))), (entry) => entry.key)].map(([key, entries]) => {
6704
6654
  const ids = entries.map((entry) => entry.id);
6705
- const lines = ids.flatMap((id) => buildLines(input, byId, id, dead, holders, system));
6655
+ const lines = ids.flatMap((id) => buildLines(input, byId, id, holders, system));
6706
6656
  const owner = key.slice(LEDGER_OWNER_PREFIX.length);
6707
6657
  const holder = input.owners.get(owner)?.[0];
6708
6658
  const title = key === "rules" ? "Rules" : holder === void 0 ? `account ${owner}` : `${holder} (account ${owner})`;
@@ -6716,17 +6666,19 @@ function buildRecords(input) {
6716
6666
  }
6717
6667
  };
6718
6668
  }).sort((left, right) => Number(left.record.key === "rules") - Number(right.record.key === "rules") || left.first - right.first || (left.record.key < right.record.key ? -1 : left.record.key > right.record.key ? 1 : 0)).map(({ record }) => record),
6719
- stale,
6669
+ amendments,
6720
6670
  orphans
6721
6671
  };
6722
6672
  }
6723
6673
  /**
6724
- * Selects a request's view of the projected records.
6674
+ * Selects a request's records, collapsing owners with equal ordered member ids under titles joined with `; `.
6725
6675
  *
6726
6676
  * @remarks
6727
6677
  * The view holds the owner records the request names in the order it names them, then the rules
6728
6678
  * record with the lines whose topics meet the request's first, each group in position order. The
6729
- * returned records and lines are copies.
6679
+ * returned records and lines are copies. Owner records with the same member ids in the same order
6680
+ * collapse into the first requested record, keeping its key, members, and lines and joining their
6681
+ * titles with `; ` before trimming.
6730
6682
  *
6731
6683
  * @param projection - The output of {@link buildRecords}
6732
6684
  * @param request - The owners and the desk topics the request names
@@ -6742,10 +6694,14 @@ function selectRecords(projection, request) {
6742
6694
  const topics = new Set(request.topics);
6743
6695
  const rules = projection.records.find((one) => one.key === LEDGER_RULES_KEY);
6744
6696
  const sides = Map.groupBy((rules?.lines ?? []).filter(() => true), (line) => line.topics.some((topic) => topics.has(topic)));
6745
- return [...[...new Set(request.owners)].flatMap((owner) => {
6697
+ const owners = [...new Set(request.owners)].flatMap((owner) => {
6746
6698
  const record = projection.records.find((one) => one.key === `${LEDGER_OWNER_PREFIX}${owner}`);
6747
- return record === void 0 ? [] : [structuredClone(record)];
6748
- }), ...rules === void 0 ? [] : [structuredClone({
6699
+ return record === void 0 ? [] : [record];
6700
+ });
6701
+ return [...[...Map.groupBy(owners, (record) => JSON.stringify(record.members)).values()].flatMap(([record, ...rest]) => record === void 0 ? [] : [structuredClone({
6702
+ ...record,
6703
+ title: [record.title, ...rest.map((one) => one.title)].join("; ")
6704
+ })]), ...rules === void 0 ? [] : [structuredClone({
6749
6705
  ...rules,
6750
6706
  lines: [...sides.get(true) ?? [], ...sides.get(false) ?? []]
6751
6707
  })]];
@@ -6757,6 +6713,7 @@ function selectRecords(projection, request) {
6757
6713
  * The briefing joins rendered records with one blank line.
6758
6714
  *
6759
6715
  * @param record - A record or view with a `title` and `lines`
6716
+ * @param context - Rendering facts for optional accepted amendment annotations
6760
6717
  * @returns `## TITLE` followed by `- LINE` for each line
6761
6718
  *
6762
6719
  * @example
@@ -6765,13 +6722,14 @@ function selectRecords(projection, request) {
6765
6722
  * // '## Rules\n- Refunds need a manager.'
6766
6723
  * ```
6767
6724
  */
6768
- function renderLedgerRecord(record) {
6769
- return [`## ${record.title}`, ...record.lines.map((line) => `- ${line.text}`)].join("\n");
6725
+ function renderLedgerRecord(record, context) {
6726
+ return [`## ${record.title}`, ...record.lines.flatMap((line) => [context === void 0 ? "" : renderLedgerAnnotation(line, context), `- ${line.text}`].filter((text) => text !== ""))].join("\n");
6770
6727
  }
6771
6728
  /**
6772
6729
  * Renders one owner record under a `###` heading, which the briefing nests under its one `## Pinned` heading.
6773
6730
  *
6774
6731
  * @param record - An owner record or view with a `title` and `lines`
6732
+ * @param context - Rendering facts for optional accepted amendment annotations
6775
6733
  * @returns `### TITLE` followed by `- LINE` for each line
6776
6734
  *
6777
6735
  * @example
@@ -6779,8 +6737,57 @@ function renderLedgerRecord(record) {
6779
6737
  * renderLedgerPinned({ title: 'Odile Marlow (account OM-30418)', lines: [] }) // '### Odile Marlow (account OM-30418)'
6780
6738
  * ```
6781
6739
  */
6782
- function renderLedgerPinned(record) {
6783
- return `#${renderLedgerRecord(record)}`;
6740
+ function renderLedgerPinned(record, context) {
6741
+ return `#${renderLedgerRecord(record, context)}`;
6742
+ }
6743
+ /**
6744
+ * Derives complete source identities, first occurrences, and local references from the actual briefing lines.
6745
+ * @param messages - Original messages whose indexed sentences establish completeness
6746
+ * @param lines - Retained lines in rendering order after deduplication and trimming
6747
+ * @param amendments - Accepted direct message amendment edges
6748
+ * @returns Immutable rendering facts for this retained population
6749
+ *
6750
+ * @example
6751
+ * ```ts
6752
+ * buildLedgerRenderContext([], [], []).complete.size // 0
6753
+ * ```
6754
+ */
6755
+ function buildLedgerRenderContext(messages, lines, amendments) {
6756
+ const identities = new Set(lines.map((line) => `${line.source} ${line.sentence}`));
6757
+ return {
6758
+ amendments,
6759
+ complete: new Set(messages.filter((message) => {
6760
+ const sentences = splitSentences(message.content);
6761
+ return sentences.length > 0 && sentences.every((_, index) => identities.has(`${message.id} ${index}`));
6762
+ }).map((message) => message.id)),
6763
+ first: new Map(lines.toReversed().map((line) => [line.source, line])),
6764
+ references: new Map([...new Set(lines.map((line) => line.source))].map((source, index) => [source, String(index + 1)]))
6765
+ };
6766
+ }
6767
+ /**
6768
+ * Renders source framing and unresolved amendment scope at a source's first retained line.
6769
+ * @param line - The retained occurrence to annotate
6770
+ * @param context - Actual complete sources, first occurrences, local references, and accepted amendment edges
6771
+ * @returns Source framing and truthful inclusion notes, or empty text for an unrelated or repeated occurrence
6772
+ * @throws {LedgerError} Thrown when the context holds no reference for the annotated source or a fully included amender (code `'REQUEST'`)
6773
+ *
6774
+ * @example
6775
+ * ```ts
6776
+ * renderLedgerAnnotation({ text: 'Unchanged.', source: 'user-1', sentence: 0, topics: [], role: 'user' }, buildLedgerRenderContext([], [], [])) // ''
6777
+ * ```
6778
+ */
6779
+ function renderLedgerAnnotation(line, context) {
6780
+ if (context.first.get(line.source) !== line) return "";
6781
+ const amendments = context.amendments.filter((pair) => pair.earlier === line.source);
6782
+ const endpoint = context.complete.has(line.source) && context.amendments.some((pair) => pair.later === line.source && context.first.has(pair.earlier));
6783
+ if (amendments.length === 0 && !endpoint) return "";
6784
+ const included = amendments.filter((pair) => context.complete.has(pair.later));
6785
+ if (context.references.get(line.source) === void 0 || included.some((pair) => context.references.get(pair.later) === void 0)) throw new LedgerError("REFERENCE", "Ledger rendering requires retained source references");
6786
+ return [
6787
+ `[Ledger source ${context.references.get(line.source)}]`,
6788
+ ...included.map((pair) => `Accepted later amendment [Ledger source ${context.references.get(pair.later)}] is fully included in this briefing. Sentence scope is unresolved.`),
6789
+ ...amendments.some((pair) => !context.complete.has(pair.later)) ? ["Accepted later amendment text is not fully included in this briefing. Sentence scope is unresolved."] : []
6790
+ ].join("\n");
6784
6791
  }
6785
6792
  /**
6786
6793
  * Splits a recall topic at its joints.
@@ -6976,74 +6983,62 @@ function placeMember(input, links, amending, id, seen, settled) {
6976
6983
  return keys;
6977
6984
  }
6978
6985
  /**
6979
- * Collects the sentences that live messages made stale.
6986
+ * Collects accepted direct amendments of live messages.
6980
6987
  *
6981
6988
  * @remarks
6982
- * A sentence of a live message is stale when it shares an id or a number with a message that
6983
- * amends it. An amending message takes effect while it is live, and keeps its effect after another
6984
- * message supersedes it, so the value it replaced never revives. A user or tool message that the
6985
- * input excludes or files quiet never takes effect.
6989
+ * An accepted edge relates an earlier live message to an amender without claiming which sentences
6990
+ * changed. An amender takes effect while live and retains its edge after another message supersedes
6991
+ * it, without restoring the superseded text. An excluded or quiet user or tool message has no effect.
6986
6992
  *
6987
6993
  * @param input - The exclusions and classification to read
6988
6994
  * @param byId - The messages by id
6989
6995
  * @param live - The live message ids from {@link collectLive}
6990
- * @returns The stale sentences in conversation order, each with the tokens it shares
6996
+ * @returns The distinct accepted direct edges in conversation order
6991
6997
  *
6992
6998
  * @example
6993
6999
  * ```ts
6994
- * collectStale(input, byId, ['user-1', 'user-3']) // [{ source: 'user-1', sentence: 1, tokens: ['ESC-2291'] }]
7000
+ * collectAmendments(input, byId, ['user-1', 'user-3']) // [{ earlier: 'user-1', later: 'user-3' }]
6995
7001
  * ```
6996
7002
  */
6997
- function collectStale(input, byId, live) {
7003
+ function collectAmendments(input, byId, live) {
6998
7004
  const { classification } = input;
6999
7005
  const excluded = new Set(input.exclusions);
7006
+ const living = new Set(live);
7007
+ const ordered = [...new Set(input.messages.map((message) => message.id))];
7008
+ const positions = new Map(ordered.map((id, index) => [id, index]));
7000
7009
  const effective = /* @__PURE__ */ new Set([...live, ...[...byId.values()].filter((message) => message.role !== "assistant" && !excluded.has(message.id) && !classification.quiet.has(message.id) && (classification.supersessions.get(message.id) ?? []).length > 0).map((message) => message.id)]);
7001
- return live.flatMap((id) => {
7002
- const laters = (classification.amendments.get(id) ?? []).filter((later) => effective.has(later)).flatMap((later) => {
7003
- const message = byId.get(later);
7004
- return message === void 0 ? [] : [extractTokens(message.content)];
7005
- });
7006
- if (laters.length === 0) return [];
7007
- return splitSentences(byId.get(id)?.content ?? "").flatMap((text, sentence) => {
7008
- const own = extractTokens(text);
7009
- const tokens = new Set(laters.flatMap((other) => [...[...own.ids].filter((token) => other.ids.has(token)), ...[...own.numbers].filter((token) => other.numbers.has(token)).map(String)]));
7010
- return tokens.size > 0 ? [{
7011
- source: id,
7012
- sentence,
7013
- tokens: [...tokens]
7014
- }] : [];
7015
- });
7016
- });
7010
+ return ordered.filter((id) => living.has(id)).flatMap((earlier) => [...new Set(classification.amendments.get(earlier) ?? [])].filter((later) => effective.has(later) && positions.has(later)).sort((a, b) => (positions.get(a) ?? 0) - (positions.get(b) ?? 0)).map((later) => ({
7011
+ earlier,
7012
+ later
7013
+ })));
7017
7014
  }
7018
7015
  /**
7019
7016
  * Builds the record lines of one message.
7020
7017
  *
7021
7018
  * @remarks
7022
- * Each sentence that is not stale becomes a line. A sentence that opens with a pronoun and follows
7019
+ * Each original indexed sentence becomes a line. A sentence that opens with a pronoun and follows
7023
7020
  * another sentence takes the last name of the sentence before it that is neither an owner name nor
7024
7021
  * a system name, and its line text opens with that party and a colon.
7025
7022
  *
7026
7023
  * @param input - The classification whose topics the lines carry
7027
7024
  * @param byId - The messages by id
7028
7025
  * @param id - The message id
7029
- * @param dead - The stale sentences as `SOURCE SENTENCE` keys
7030
7026
  * @param holders - The owner names, which never serve as a party
7031
7027
  * @param system - The system text's names, which never serve as a party
7032
7028
  * @returns The lines in sentence order; empty when the message is absent
7033
7029
  *
7034
7030
  * @example
7035
7031
  * ```ts
7036
- * buildLines(input, byId, 'user-1', new Set(), [], []).map((line) => line.text)
7032
+ * buildLines(input, byId, 'user-1', [], []).map((line) => line.text)
7037
7033
  * // ['Odile Marlow phoned about BW-5512.', 'Odile Marlow: She wants a refund.']
7038
7034
  * ```
7039
7035
  */
7040
- function buildLines(input, byId, id, dead, holders, system) {
7036
+ function buildLines(input, byId, id, holders, system) {
7041
7037
  const message = byId.get(id);
7042
7038
  if (message === void 0) return [];
7043
7039
  const sentences = splitSentences(message.content);
7044
7040
  const topics = input.classification.topics.get(id) ?? [];
7045
7041
  return sentences.flatMap((sentence, at) => {
7046
- if (dead.has(`${id} ${at}`)) return [];
7047
7042
  const party = /^(?:He|She|They|His|Her|Their)(?![\p{L}\p{N}])/u.test(sentence) && at > 0 ? collectNames(sentences[at - 1] ?? "").filter((name) => !holders.includes(name) && !system.includes(name)).at(-1) : void 0;
7048
7043
  const line = {
7049
7044
  text: party === void 0 ? sentence : `${party}: ${sentence}`,
@@ -7058,8 +7053,7 @@ function buildLines(input, byId, id, dead, holders, system) {
7058
7053
  }];
7059
7054
  });
7060
7055
  }
7061
- //#endregion
7062
- //#region src/core/ledgers/Classifier.ts
7056
+ // src/core/ledgers/Classifier.ts
7063
7057
  /**
7064
7058
  * Files messages through the conversation's judgment manager and reads their categories and corrections.
7065
7059
  *
@@ -7345,8 +7339,7 @@ var Classifier = class {
7345
7339
  }
7346
7340
  }
7347
7341
  };
7348
- //#endregion
7349
- //#region src/core/ledgers/validators.ts
7342
+ // src/core/ledgers/validators.ts
7350
7343
  /**
7351
7344
  * Checks whether a value is finite and lies in the interval (0, 1].
7352
7345
  * @param value - The value to inspect
@@ -7371,8 +7364,7 @@ function isFraction(value) {
7371
7364
  function isPositiveSafeInteger(value) {
7372
7365
  return isFiniteNumber(value) && Number.isSafeInteger(value) && value > 0;
7373
7366
  }
7374
- //#endregion
7375
- //#region src/core/ledgers/Gauge.ts
7367
+ // src/core/ledgers/Gauge.ts
7376
7368
  /**
7377
7369
  * Prices prompts in tokens from a measured scale and overhead cost, and measures the room a request
7378
7370
  * has left.
@@ -7465,8 +7457,7 @@ var Gauge = class {
7465
7457
  if (isFiniteNumber(reply?.completion)) this.#reply = Math.max(this.#reply, reply.completion - (reply.thinking ?? 0));
7466
7458
  }
7467
7459
  };
7468
- //#endregion
7469
- //#region src/core/ledgers/LedgerPass.ts
7460
+ // src/core/ledgers/LedgerPass.ts
7470
7461
  /**
7471
7462
  * Holds what one pass of a ledger request keeps: the selection its run adopted last, the
7472
7463
  * conversation boundary its calls count additions from, its summed usage, and its gauge calls.
@@ -7610,8 +7601,7 @@ var LedgerPass = class {
7610
7601
  this.#log = [...this.#log, { thinking }];
7611
7602
  }
7612
7603
  };
7613
- //#endregion
7614
- //#region src/core/ledgers/LedgerRequest.ts
7604
+ // src/core/ledgers/LedgerRequest.ts
7615
7605
  /**
7616
7606
  * Holds what one ledger request keeps while it is served: its message, its filing readings and
7617
7607
  * plan, the gauge calls of its passes, and its repeat and recall stops.
@@ -7764,8 +7754,7 @@ var LedgerRequest = class {
7764
7754
  return this.#listings.get(result);
7765
7755
  }
7766
7756
  };
7767
- //#endregion
7768
- //#region src/core/ledgers/Ledger.ts
7757
+ // src/core/ledgers/Ledger.ts
7769
7758
  /**
7770
7759
  * Serves one conversation through classified records, a bounded briefing, and a final answer pass.
7771
7760
  * @example
@@ -8123,17 +8112,17 @@ var Ledger = class {
8123
8112
  projection: buildRecords(input)
8124
8113
  };
8125
8114
  }
8126
- #projectLines(input, projection, id) {
8127
- return buildLines(input, new Map(input.messages.map((message) => [message.id, message])), id, new Set(projection.stale.map((line) => `${line.source} ${line.sentence}`)), [...input.owners.values()].flat(), collectNames(this.#options.system));
8115
+ #projectLines(input, id) {
8116
+ return buildLines(input, new Map(input.messages.map((message) => [message.id, message])), id, [...input.owners.values()].flat(), collectNames(this.#options.system));
8128
8117
  }
8129
- #renderSource(id, lines) {
8118
+ #renderSource(id, lines, context) {
8130
8119
  const message = this.#conversation.message(id);
8131
8120
  if (message === void 0) return "";
8132
8121
  const sentences = splitSentences(message.content);
8133
- const text = sentences.length === lines.length ? message.content : lines.map((line) => sentences[line.sentence] ?? "").join(" ");
8134
- if (text === "" || message.role !== "tool") return text;
8122
+ const text = sentences.every((_, index) => lines.some((line) => line.sentence === index)) ? message.content : lines.map((line) => sentences[line.sentence] ?? "").join(" ");
8123
+ if (text === "") return "";
8135
8124
  const reading = this.#readLookups().find((one) => one.id === id);
8136
- return reading === void 0 ? text : `${renderLookupCall(reading.name, reading.arguments)}: ${text}`;
8125
+ return [...lines.map((line) => renderLedgerAnnotation(line, context)), message.role !== "tool" || reading === void 0 ? text : `${renderLookupCall(reading.name, reading.arguments)}: ${text}`].filter((part) => part !== "").join("\n");
8137
8126
  }
8138
8127
  #collectAfter(request) {
8139
8128
  const messages = this.#conversation.messages();
@@ -8216,7 +8205,7 @@ var Ledger = class {
8216
8205
  const score = [...words].filter((word) => asked?.words.has(word)).reduce((sum, word) => sum + Math.log(texts.length / (counts.get(word) ?? 1)), 0);
8217
8206
  return [{
8218
8207
  source: message.id,
8219
- lines: this.#projectLines(input, projection, message.id),
8208
+ lines: this.#projectLines(input, message.id),
8220
8209
  position,
8221
8210
  group,
8222
8211
  ruled,
@@ -8250,7 +8239,7 @@ var Ledger = class {
8250
8239
  source: unit.source,
8251
8240
  record: this.#buildUnitRecord(unit.source, unit.category, input, projection, held)
8252
8241
  }));
8253
- const trimmed = this.#trim(steps, records, mapped, new Set(ordered.map((unit) => unit.source)), cap);
8242
+ const trimmed = this.#trim(steps, records, mapped, new Set(ordered.map((unit) => unit.source)), cap, projection.amendments);
8254
8243
  const briefing = trimmed.briefing;
8255
8244
  const shown = /* @__PURE__ */ new Set([...trimmed.included, ...records.flatMap((record) => record.members.filter((source) => {
8256
8245
  const full = record.lines.filter((line) => line.source === source);
@@ -8262,10 +8251,10 @@ var Ledger = class {
8262
8251
  ...briefing === "" ? {} : { briefing }
8263
8252
  };
8264
8253
  }
8265
- #trim(steps, records, mapped, included, cap) {
8254
+ #trim(steps, records, mapped, included, cap, amendments) {
8266
8255
  const trimmed = steps.reduce((cut, step) => {
8267
8256
  if (cut.briefing !== void 0) return cut;
8268
- const briefing = this.#render(cut.records, mapped, cut.included);
8257
+ const briefing = this.#render(cut.records, mapped, cut.included, amendments);
8269
8258
  const content = [this.#options.system, briefing].filter((part) => part !== "").join("\n\n");
8270
8259
  if (this.#price([{
8271
8260
  id: "system",
@@ -8291,7 +8280,7 @@ var Ledger = class {
8291
8280
  return {
8292
8281
  records: trimmed.records,
8293
8282
  included: trimmed.included,
8294
- briefing: trimmed.briefing ?? this.#render(trimmed.records, mapped, trimmed.included)
8283
+ briefing: trimmed.briefing ?? this.#render(trimmed.records, mapped, trimmed.included, amendments)
8295
8284
  };
8296
8285
  }
8297
8286
  #buildUnitRecord(source, category, input, projection, held) {
@@ -8304,25 +8293,33 @@ var Ledger = class {
8304
8293
  }
8305
8294
  #collectAmended(input, projection, source, held) {
8306
8295
  const live = collectProjectionIds(projection);
8307
- return scanAmendments(input.classification.amendments, source, (id) => id === source || !held.has(id) && live.has(id)).flatMap((id) => this.#projectLines(input, projection, id));
8296
+ return scanAmendments(input.classification.amendments, source, (id) => id === source || !held.has(id) && live.has(id)).flatMap((id) => this.#projectLines(input, id));
8308
8297
  }
8309
- #render(records, mapped, included) {
8310
- const owners = records.filter((record) => record.key !== "rules" && record.lines.length > 0).map(renderLedgerPinned).join("\n\n");
8298
+ #render(records, mapped, included, amendments) {
8311
8299
  const entries = mapped.filter((unit) => included.has(unit.source)).flatMap(({ record: unit }) => [...Map.groupBy(unit.lines, (line) => line.source)].map(([source, lines]) => ({
8312
8300
  unit,
8313
8301
  source,
8314
8302
  lines
8315
8303
  })));
8316
8304
  const first = new Map(entries.toReversed().map((entry) => [entry.source, entry]));
8317
- const rendered = entries.filter((entry) => first.get(entry.source) === entry).map(({ unit, source, lines }) => ({
8305
+ const unique = entries.filter((entry) => first.get(entry.source) === entry);
8306
+ const record = records.find((candidate) => candidate.key === "rules" && candidate.lines.length > 0);
8307
+ const ownerRecords = records.filter((candidate) => candidate.key !== "rules" && candidate.lines.length > 0);
8308
+ const context = buildLedgerRenderContext(this.#conversation.messages(), [
8309
+ ...ownerRecords.flatMap((candidate) => candidate.lines),
8310
+ ...unique.filter((entry) => entry.unit.key !== LEDGER_RULES_KEY).flatMap((entry) => entry.lines),
8311
+ ...record?.lines ?? [],
8312
+ ...unique.filter((entry) => entry.unit.key === LEDGER_RULES_KEY).flatMap((entry) => entry.lines)
8313
+ ], amendments);
8314
+ const owners = ownerRecords.map((owner) => renderLedgerPinned(owner, context)).join("\n\n");
8315
+ const rendered = unique.map(({ unit, source, lines }) => ({
8318
8316
  rules: unit.key === LEDGER_RULES_KEY,
8319
- texts: unit.key === "rules" && source === unit.members[0] ? lines.map((line) => this.#renderSource(source, [line])) : [this.#renderSource(source, lines)]
8317
+ texts: unit.key === "rules" && source === unit.members[0] ? lines.map((line) => this.#renderSource(source, [line], context)) : [this.#renderSource(source, lines, context)]
8320
8318
  }));
8321
8319
  const pinned = rendered.filter((one) => !one.rules).flatMap((one) => one.texts);
8322
8320
  const rules = rendered.filter((one) => one.rules).flatMap((one) => one.texts);
8323
8321
  const body = [owners, pinned.join("\n")].filter((text) => text !== "").join("\n\n");
8324
- const record = records.find((candidate) => candidate.key === "rules" && candidate.lines.length > 0);
8325
- return [body === "" ? "" : `## Pinned\n${body}`, record === void 0 ? rules.length === 0 ? "" : ["## Rules", ...rules].join("\n") : [renderLedgerRecord(record), ...rules].join("\n")].filter((text) => text !== "").join("\n\n");
8322
+ return [body === "" ? "" : `## Pinned\n${body}`, record === void 0 ? rules.length === 0 ? "" : ["## Rules", ...rules].join("\n") : [renderLedgerRecord(record, context), ...rules].join("\n")].filter((text) => text !== "").join("\n\n");
8326
8323
  }
8327
8324
  #selectTail(request, cap, input) {
8328
8325
  const first = input.messages.findIndex((message) => this.#requests.has(message.id));
@@ -8462,8 +8459,7 @@ var Ledger = class {
8462
8459
  return lines.length === 0 ? void 0 : `${LEDGER_NOTES.results}\n${lines.join("\n")}`;
8463
8460
  }
8464
8461
  };
8465
- //#endregion
8466
- //#region src/core/ledgers/factories.ts
8462
+ // src/core/ledgers/factories.ts
8467
8463
  /**
8468
8464
  * Creates a conversation ledger after checking its thresholds, allocation, and tool names.
8469
8465
  * @param provider - The provider that answers requests
@@ -8479,7 +8475,6 @@ var Ledger = class {
8479
8475
  function createLedger(provider, options) {
8480
8476
  return new Ledger(provider, options);
8481
8477
  }
8482
- //#endregion
8483
- export { Agent, AgentContext, AgentError, AgentFanout, AgentJobError, AgentJudge, AgentProvider, AgentRegistry, Authority, CONVERSATION_RECAP_PREFIX, Channel, Classifier, Conversation, ConversationError, ConversationManager, DECISIVE_CATEGORIES, DEFAULT_AGENT_LIMIT, DEFAULT_AUTHORITY_ZONE, DEFAULT_CONVERSATION_KEEP, DEFAULT_LEDGER_LIMIT, DEFAULT_LEDGER_SHARE, DEFAULT_PROVIDER_TIMEOUT, DEFAULT_RECALL_LIMIT, DEFAULT_RELAY_LIMIT, DETERMINISTIC_JUDGE_ERROR, DatabaseConversationStore, Gauge, IMAGE_TOKEN_ESTIMATE, INVALID_RELAY_STATUS, Instruction, InstructionManager, JudgeAbortError, JudgeError, JudgmentManager, LEDGER_CATEGORIES, LEDGER_NOTES, LEDGER_OWNER_PREFIX, LEDGER_QUESTIONS, LEDGER_RULES_KEY, LEDGER_SCALE_DRIFT, Ledger, LedgerError, LedgerRequest, MAX_ERROR_BODY_LENGTH, MESSAGE_ROLES, MESSAGE_TOKEN_OVERHEAD, MemoryConversationStore, OVERSIZED_RELAY_STATUS, PLACED_CATEGORIES, ProviderAbortError, ProviderError, QUIET_CATEGORIES, RELAY_CONTENT_TYPE, RELAY_PROVIDER_MESSAGE, RelayProvider, RelayStream, SYSTEM_ONE_PATH, Scope, ScopeManager, SystemOneJudge, THINK_CLOSE, THINK_OPEN, ThinkSplitter, UNAUTHORIZED_RELAY_STATUS, UPSTREAM_RELAY_STATUS, WORKSPACE_SECTION_HEADER, agentResultToJSON, armReaderAbort, assembleResult, attachImages, attachUserImages, buildJudgeResult, buildJudgments, buildLines, buildProviderHeaders, buildProviderResult, buildRecallMessage, buildRecapMessage, buildRecords, buildSummaryMessage, chargeUsage, collectExchanges, collectImageData, collectLive, collectNames, collectProjectionIds, collectRegistry, collectStale, collectToolGroups, computeReading, computeThinking, copyJSON, createAgent, createAgentContext, createAgentQueue, createAgentRegistry, createAgentRunner, createAuthority, createChannel, createConversation, createConversationManager, createDatabaseConversationStore, createInstruction, createInstructionManager, createLedger, createMemoryConversationStore, createRelay, createRelayProvider, createScope, createScopeManager, createSystemOneJudge, createThinkSplitter, cutListing, denyCall, estimateMessages, estimateRequest, estimateTokens, extractQueueOptions, extractSystemOneAnswer, extractSystemOneUsage, extractTokens, extractWords, filterAllowList, findLedgerCall, fitSlope, handleAgentQueueJob, hasCalls, identifyLookup, inferStop, intersectKeys, isAgentError, isAgentJobError, isConversationError, isConversationSnapshot, isFraction, isJudgeAbortError, isJudgeEntry, isJudgeError, isJudgeQuestion, isJudgment, isLedgerError, isMessage, isNonNegativeSafeInteger, isPositiveSafeInteger, isProviderAbortError, isProviderError, isSection, isSystemOneAnswer, isSystemOneResponse, joinThinking, linkOwners, matchEntities, matchesCutLine, matchesJudgment, measureMessage, measureRequest, messageContract, messageShape, normalizeArgument, placeMember, providerRequestContract, providerRequestShape, providerResultContract, providerResultShape, questionToSystemOne, raceSignal, rankLedgerCut, readChunks, readFailure, readText, relayFrameContract, relayFrameShape, releaseReader, removeEntries, renderCauseChain, renderFencedFile, renderJSON, renderLedgerPinned, renderLedgerRecord, renderLookupCall, renderSection, renderStub, renderToolValue, renderTopicNames, requestToRelay, requireBudget, requireEntry, requireJudgment, requireKeep, requireLimit, requireRolling, requireSectionsCap, resolvePredict, sanitizeToken, sanitizeUsage, scanAmendments, selectRecords, settleAgentJob, splitResultLines, splitSentences, splitTopic, splitWords, stripThinking, sumUsage, tokenUsageToJSON, toolCallShape };
8478
+ export { Agent, AgentContext, AgentError, AgentFanout, AgentJobError, AgentJudge, AgentProvider, AgentRegistry, Authority, CONVERSATION_RECAP_PREFIX, Channel, Classifier, Conversation, ConversationError, ConversationManager, DECISIVE_CATEGORIES, DEFAULT_AGENT_LIMIT, DEFAULT_AUTHORITY_ZONE, DEFAULT_CONVERSATION_KEEP, DEFAULT_LEDGER_LIMIT, DEFAULT_LEDGER_SHARE, DEFAULT_PROVIDER_TIMEOUT, DEFAULT_RECALL_LIMIT, DEFAULT_RELAY_LIMIT, DETERMINISTIC_JUDGE_ERROR, DatabaseConversationStore, Gauge, IMAGE_TOKEN_ESTIMATE, INVALID_RELAY_STATUS, Instruction, InstructionManager, JudgeAbortError, JudgeError, JudgmentManager, LEDGER_CATEGORIES, LEDGER_NOTES, LEDGER_OWNER_PREFIX, LEDGER_QUESTIONS, LEDGER_RULES_KEY, LEDGER_SCALE_DRIFT, Ledger, LedgerError, LedgerRequest, MAX_ERROR_BODY_LENGTH, MESSAGE_ROLES, MESSAGE_TOKEN_OVERHEAD, MemoryConversationStore, OVERSIZED_RELAY_STATUS, PLACED_CATEGORIES, ProviderAbortError, ProviderError, QUIET_CATEGORIES, RELAY_CONTENT_TYPE, RELAY_PROVIDER_MESSAGE, RelayProvider, RelayStream, SYSTEM_ONE_PATH, Scope, ScopeManager, SystemOneJudge, THINK_CLOSE, THINK_OPEN, ThinkSplitter, UNAUTHORIZED_RELAY_STATUS, UPSTREAM_RELAY_STATUS, WORKSPACE_SECTION_HEADER, agentResultToJSON, armReaderAbort, assembleResult, attachImages, attachUserImages, buildJudgeResult, buildJudgments, buildLedgerRenderContext, buildLines, buildProviderHeaders, buildProviderResult, buildRecallMessage, buildRecapMessage, buildRecords, buildSummaryMessage, chargeUsage, collectAmendments, collectExchanges, collectImageData, collectLive, collectNames, collectProjectionIds, collectRegistry, collectToolGroups, computeReading, computeThinking, copyJSON, createAgent, createAgentContext, createAgentQueue, createAgentRegistry, createAgentRunner, createAuthority, createChannel, createConversation, createConversationManager, createDatabaseConversationStore, createInstruction, createInstructionManager, createLedger, createMemoryConversationStore, createRelay, createRelayProvider, createScope, createScopeManager, createSystemOneJudge, createThinkSplitter, cutListing, denyCall, estimateMessages, estimateRequest, estimateTokens, extractQueueOptions, extractSystemOneAnswer, extractSystemOneUsage, extractTokens, extractWords, filterAllowList, findLedgerCall, fitSlope, handleAgentQueueJob, hasCalls, identifyLookup, inferStop, intersectKeys, isAgentError, isAgentJobError, isConversationError, isConversationSnapshot, isFraction, isJudgeAbortError, isJudgeEntry, isJudgeError, isJudgeQuestion, isJudgment, isLedgerError, isMessage, isNonNegativeSafeInteger, isPositiveSafeInteger, isProviderAbortError, isProviderError, isSection, isSystemOneAnswer, isSystemOneResponse, joinThinking, linkOwners, matchEntities, matchesCutLine, matchesJudgment, measureMessage, measureRequest, messageContract, messageShape, normalizeArgument, placeMember, providerRequestContract, providerRequestShape, providerResultContract, providerResultShape, questionToSystemOne, raceSignal, rankLedgerCut, readChunks, readFailure, readText, relayFrameContract, relayFrameShape, releaseReader, removeEntries, renderCauseChain, renderFencedFile, renderJSON, renderLedgerAnnotation, renderLedgerPinned, renderLedgerRecord, renderLookupCall, renderSection, renderStub, renderToolValue, renderTopicNames, requestToRelay, requireBudget, requireEntry, requireJudgment, requireKeep, requireLimit, requireRolling, requireSectionsCap, resolvePredict, sanitizeToken, sanitizeUsage, scanAmendments, selectRecords, settleAgentJob, splitResultLines, splitSentences, splitTopic, splitWords, stripThinking, sumUsage, tokenUsageToJSON, toolCallShape };
8484
8479
 
8485
8480
  //# sourceMappingURL=index.js.map