@sema-agent/core 5.57.0 → 5.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/agents/cascade.d.ts +1 -1
  3. package/dist/agents/cumulative-stats.d.ts +1 -1
  4. package/dist/agents/observer.d.ts +2 -2
  5. package/dist/agents/peer-admission.d.ts +1 -1
  6. package/dist/agents/retain-ledger.d.ts +2 -2
  7. package/dist/agents/roster-store.d.ts +8 -8
  8. package/dist/agents/send-message-tool.d.ts +2 -2
  9. package/dist/agents/subagent-steps.d.ts +1 -1
  10. package/dist/agents/subagent.d.ts +13 -13
  11. package/dist/agents/team.d.ts +5 -5
  12. package/dist/agents/tool-filter.d.ts +2 -2
  13. package/dist/agents/verify.d.ts +1 -1
  14. package/dist/bench/metrics.d.ts +35 -35
  15. package/dist/brain/degrading.d.ts +1 -1
  16. package/dist/brain/errors.d.ts +3 -3
  17. package/dist/brain/reasoning.d.ts +2 -2
  18. package/dist/brain/repetition.d.ts +1 -1
  19. package/dist/brain/status-sink.d.ts +2 -2
  20. package/dist/brain/stream-shared.d.ts +1 -1
  21. package/dist/config/catalog.d.ts +5 -5
  22. package/dist/core/arg-summary.d.ts +4 -4
  23. package/dist/core/ask-class.d.ts +2 -2
  24. package/dist/core/ask-question.d.ts +1 -1
  25. package/dist/core/auto-compaction.d.ts +15 -15
  26. package/dist/core/auto-mode.d.ts +5 -5
  27. package/dist/core/background-agent-store.d.ts +20 -20
  28. package/dist/core/background-shell.d.ts +4 -4
  29. package/dist/core/checkpoint-store.d.ts +35 -27
  30. package/dist/core/context-edit.d.ts +1 -1
  31. package/dist/core/context-guard.d.ts +1 -1
  32. package/dist/core/exec-output-tail.d.ts +6 -6
  33. package/dist/core/file-snapshot-store.d.ts +8 -8
  34. package/dist/core/git-worktree-env.d.ts +3 -3
  35. package/dist/core/governance-codes.js +2 -0
  36. package/dist/core/hooks.d.ts +73 -33
  37. package/dist/core/hooks.js +87 -25
  38. package/dist/core/image-downsample.d.ts +1 -1
  39. package/dist/core/locked-config.d.ts +1 -1
  40. package/dist/core/lsp.d.ts +1 -1
  41. package/dist/core/mailbox-store.d.ts +1 -1
  42. package/dist/core/mcp.d.ts +3 -3
  43. package/dist/core/memory-engine/consolidation-driver.d.ts +207 -0
  44. package/dist/core/memory-engine/consolidation-driver.js +378 -0
  45. package/dist/core/memory-engine/consolidation.d.ts +46 -2
  46. package/dist/core/memory-engine/consolidation.js +1 -0
  47. package/dist/core/memory-engine/data-plane.d.ts +1 -1
  48. package/dist/core/memory-engine/distiller.d.ts +550 -0
  49. package/dist/core/memory-engine/distiller.js +598 -0
  50. package/dist/core/memory-engine/dual-root.d.ts +1 -1
  51. package/dist/core/memory-engine/engine.d.ts +47 -3
  52. package/dist/core/memory-engine/engine.js +37 -3
  53. package/dist/core/memory-engine/file-backend.d.ts +1 -1
  54. package/dist/core/memory-engine/index.d.ts +4 -2
  55. package/dist/core/memory-engine/index.js +4 -2
  56. package/dist/core/memory-engine/origin-clearance.d.ts +1 -1
  57. package/dist/core/memory-engine/scope-contract.d.ts +4 -4
  58. package/dist/core/memory-engine/sync-client.d.ts +16 -16
  59. package/dist/core/memory-engine/sync.d.ts +4 -4
  60. package/dist/core/memory-recall.d.ts +1 -1
  61. package/dist/core/memory.d.ts +2 -2
  62. package/dist/core/permission-rule-consent.d.ts +185 -36
  63. package/dist/core/permission-rule-consent.js +219 -44
  64. package/dist/core/permission-rule-model.d.ts +194 -31
  65. package/dist/core/permission-rule-model.js +93 -35
  66. package/dist/core/permission-rules.d.ts +9 -9
  67. package/dist/core/remote-env.d.ts +8 -8
  68. package/dist/core/roles.d.ts +3 -3
  69. package/dist/core/roles.js +1 -0
  70. package/dist/core/runner/assemble-result.d.ts +2 -2
  71. package/dist/core/runner/compaction-call-options.d.ts +3 -3
  72. package/dist/core/runner/memory-consolidation-driver.d.ts +49 -0
  73. package/dist/core/runner/memory-consolidation-driver.js +60 -0
  74. package/dist/core/runner/memory-consolidation.d.ts +1 -1
  75. package/dist/core/runner/prepare-config-doors.d.ts +3 -3
  76. package/dist/core/runner/prepare-task.d.ts +21 -21
  77. package/dist/core/runner/prepare-task.js +21 -14
  78. package/dist/core/runner/prepare-workspace-restore.d.ts +2 -2
  79. package/dist/core/runner/runtask.d.ts +11 -11
  80. package/dist/core/runner/session-rule-policy.d.ts +1 -1
  81. package/dist/core/runner/teardown-bounded.d.ts +1 -1
  82. package/dist/core/runner/tool-disclosure.d.ts +2 -2
  83. package/dist/core/runner/turn-attachments.d.ts +11 -11
  84. package/dist/core/scheduler.d.ts +5 -5
  85. package/dist/core/secret-env.d.ts +1 -1
  86. package/dist/core/sensitive-path-policy.d.ts +1 -1
  87. package/dist/core/session-policy-store.d.ts +2 -2
  88. package/dist/core/session-reconcile.d.ts +2 -2
  89. package/dist/core/session-store.d.ts +3 -3
  90. package/dist/core/session.d.ts +1 -1
  91. package/dist/core/shutdown-debug.d.ts +2 -2
  92. package/dist/core/side-query.d.ts +2 -2
  93. package/dist/core/spec-contract.d.ts +1 -1
  94. package/dist/core/store-contracts/contract-harness.d.ts +2 -2
  95. package/dist/core/store-contracts/contract-kit-version.d.ts +2 -2
  96. package/dist/core/store-contracts/mailbox-store-contract.d.ts +1 -1
  97. package/dist/core/store-contracts/mailbox-store-contract.js +1 -1
  98. package/dist/core/task-notification.d.ts +5 -5
  99. package/dist/core/task-registry-agent.d.ts +12 -12
  100. package/dist/core/task-registry-monitor.d.ts +1 -1
  101. package/dist/core/task-registry-shared.d.ts +41 -41
  102. package/dist/core/task-registry.d.ts +12 -12
  103. package/dist/core/tool-detach.d.ts +2 -2
  104. package/dist/core/tool-errors.d.ts +3 -3
  105. package/dist/core/tool-policy.d.ts +55 -28
  106. package/dist/core/tool-result-budget.d.ts +1 -1
  107. package/dist/core/tool-result-store.d.ts +2 -2
  108. package/dist/core/tools.d.ts +1 -1
  109. package/dist/core/trace.d.ts +26 -23
  110. package/dist/core/types.d.ts +123 -70
  111. package/dist/core/untrusted-egress.d.ts +1 -1
  112. package/dist/core/untrusted-text.d.ts +7 -7
  113. package/dist/core/wiring-manifest.d.ts +5 -5
  114. package/dist/core/workflow-journal-store.d.ts +14 -14
  115. package/dist/core/workflow-run-store-contract.d.ts +1 -1
  116. package/dist/core/workflow-run-store-contract.js +1 -1
  117. package/dist/core/workflow-run-store.d.ts +4 -4
  118. package/dist/engine/compaction/compaction.d.ts +3 -3
  119. package/dist/engine/compaction/utils.d.ts +2 -2
  120. package/dist/engine/execution-env/kill-tree.d.ts +1 -1
  121. package/dist/engine/execution-env/node-execution-env.d.ts +8 -8
  122. package/dist/engine/harness/agent-harness.d.ts +6 -6
  123. package/dist/engine/harness/messages.d.ts +1 -1
  124. package/dist/engine/harness/types.d.ts +10 -10
  125. package/dist/engine/llm/types.d.ts +14 -14
  126. package/dist/engine/loop/agent-loop.d.ts +3 -3
  127. package/dist/engine/loop/types.d.ts +4 -4
  128. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  129. package/dist/engine/session/import-validate.d.ts +1 -1
  130. package/dist/engine/session/log-digest.d.ts +1 -1
  131. package/dist/engine/session/memory-repo.d.ts +2 -2
  132. package/dist/engine/session/session.d.ts +4 -4
  133. package/dist/fixtures/index.d.ts +4 -4
  134. package/dist/index.d.ts +5 -4
  135. package/dist/index.js +3 -2
  136. package/dist/orchestration/goal.d.ts +1 -1
  137. package/dist/orchestration/run-spec.d.ts +1 -1
  138. package/dist/orchestration/run-workflow-tool.d.ts +12 -12
  139. package/dist/orchestration/workflow-governance.d.ts +4 -4
  140. package/dist/orchestration/workflow-observe.d.ts +1 -1
  141. package/dist/orchestration/workflow-script-runner.d.ts +1 -1
  142. package/dist/orchestration/workflow-script-store.d.ts +9 -9
  143. package/dist/orchestration/workflow-size-guideline.d.ts +1 -1
  144. package/dist/orchestration/workflow-types.d.ts +5 -5
  145. package/dist/orchestration/workflow.d.ts +10 -10
  146. package/dist/prompt-assembly/artifact-store.d.ts +1 -1
  147. package/dist/prompt-assembly/artifact.d.ts +1 -1
  148. package/dist/prompt-assembly/assemble.d.ts +1 -1
  149. package/dist/prompt-assembly/composer.d.ts +2 -2
  150. package/dist/prompt-assembly/epoch.d.ts +2 -2
  151. package/dist/prompt-assembly/event-registry.d.ts +1 -1
  152. package/dist/prompt-assembly/explain.d.ts +3 -3
  153. package/dist/prompt-assembly/tool-catalog.d.ts +1 -1
  154. package/dist/prompt-assembly/turn-snapshot.d.ts +4 -4
  155. package/dist/prompt-assembly/types.d.ts +12 -12
  156. package/dist/prompts/coordinator.d.ts +1 -1
  157. package/dist/prompts/default.d.ts +8 -8
  158. package/dist/prompts/simple-sections.d.ts +3 -3
  159. package/dist/prompts/supervisor.d.ts +2 -2
  160. package/dist/scenarios/full-body.d.ts +3 -3
  161. package/dist/scenarios/scenario-registry.d.ts +1 -1
  162. package/dist/stores/cc/sidecar-transcript.d.ts +3 -3
  163. package/dist/stores/file/fs-atomic.d.ts +2 -2
  164. package/dist/stores/file/index.d.ts +1 -1
  165. package/dist/stores/file/session-store.d.ts +2 -2
  166. package/dist/stores/file/workflow-journal-store.d.ts +4 -4
  167. package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
  168. package/dist/tools/fs/encoding.d.ts +4 -4
  169. package/dist/tools/fs/fs-bash.d.ts +3 -3
  170. package/dist/tools/fs/fs-pdf.d.ts +1 -1
  171. package/dist/tools/fs/fs-shared.d.ts +6 -6
  172. package/dist/tools/fs/index.d.ts +2 -2
  173. package/dist/tools/fs/notebook.d.ts +1 -1
  174. package/dist/tools/fs/pdf.d.ts +1 -1
  175. package/dist/tools/fs/read-deny.d.ts +1 -1
  176. package/dist/tools/fs/safety.d.ts +9 -9
  177. package/dist/tools/fs/search.d.ts +2 -2
  178. package/dist/tools/monitor.d.ts +3 -3
  179. package/dist/tools/task-list.d.ts +2 -2
  180. package/dist/tools/web.d.ts +4 -4
  181. package/dist/tools/worktree.d.ts +5 -5
  182. package/package.json +1 -1
  183. package/test/export-surface.snapshot.json +56 -3
@@ -0,0 +1,550 @@
1
+ /**
2
+ * design/376 片① — the LLM distillation DRIVER's single source (the "driver half" of design/339
3
+ * §1.1: the driver proposes, the engine adjudicates). Everything here is the product code the
4
+ * memory benchmark measures — the bench adapters import THESE exports, so every compare run is an
5
+ * end-to-end regression of the shipped driver (the true-load-path law: the bytes the rig scores
6
+ * are the bytes the npm package ships).
7
+ *
8
+ * Structure, and why each piece lives here:
9
+ * - the PROMPT CONTRACT (frozen, versioned): the prompt is a behavior surface. v1 of the product
10
+ * contract is the dl-3 contract BYTE-IDENTICAL — the version whose readings the benchmark
11
+ * archived. Any change to these strings is a NEW contract version and must produce bench
12
+ * readings before it ships (no-readings prompt edits are unreviewed behavior changes).
13
+ * - `parseJsonAnswer` / `sanitizeLlmGroups` / `planParseRepairs`: the structural adapter between
14
+ * a model answer and a protocol-shaped proposal, every repair COUNTED (a silent repair lets a
15
+ * sloppy plan read as a clean one).
16
+ * - `scheduleUnderFuse`: the driver-side plan selection under the engine's supersession fuse
17
+ * (next-fit decreasing, no backfill). The ceiling itself is NEVER re-derived here — callers
18
+ * compute it with the engine's own exported `supersessionFuseCeiling` (a second implementation
19
+ * would be a drift seam).
20
+ * - `mintLlmConsolidationPlan`: the live half (grouping + writing passes), archiving everything
21
+ * the model was told and answered.
22
+ * - `llmPlanDistiller`: a minted plan replayed as a per-cycle distiller (the run-cache form: mint
23
+ * once, filter per cycle — never re-mint inside one run).
24
+ * - `driveConsolidationToFixpoint`: the host loop over the four engine verbs (snapshot → commit →
25
+ * reconcile, repeated), counting exclusively STORE deltas.
26
+ *
27
+ * The engine holds no distillation power and no model seat (design/339 §1.1 boundary): this module
28
+ * calls the engine's HOST verbs and nothing else writes.
29
+ */
30
+ import type { MemoryEntry } from "./types.js";
31
+ import type { ConsolidationProposal } from "./consolidation.js";
32
+ export declare const DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT = 32;
33
+ export interface LlmDistillerContract {
34
+ /** The contract's registered version id (a NEW id for any byte change, with bench readings). */
35
+ version: string;
36
+ grouping: {
37
+ system: string;
38
+ instructionLines: readonly string[];
39
+ instructions: string;
40
+ };
41
+ writing: {
42
+ system: string;
43
+ instructions: string;
44
+ };
45
+ sampling: {
46
+ temperature: number;
47
+ maxTokens: {
48
+ grouping: number;
49
+ writing: number;
50
+ };
51
+ };
52
+ /** Format-failure retries per call. Frozen INTO the contract: the archived readings were taken
53
+ * under this value, so changing it moves the thing under measurement. */
54
+ retries: number;
55
+ }
56
+ export declare const LLM_DISTILLER_CONTRACT: LlmDistillerContract;
57
+ /** dl-2: the SAME contract with the retrievability clause disambiguated, nothing else touched. */
58
+ export declare const LLM_DISTILLER_CONTRACT_DL2: LlmDistillerContract;
59
+ /** dl-3: dl-2 with the SIZE clause substituted, nothing else touched. */
60
+ export declare const LLM_DISTILLER_CONTRACT_DL3: LlmDistillerContract;
61
+ export declare const LLM_DISTILLER_CONTRACTS: Record<string, LlmDistillerContract>;
62
+ /**
63
+ * The PRODUCT contract, v1 = dl-3 byte-identical (the version whose benchmark readings are
64
+ * archived). The shipping rule this alias exists to make auditable: a change to the product prompt
65
+ * is a NEW `version` (pd-2, …) and must produce rig readings BEFORE it ships — the contract-hash
66
+ * pin in the test suite reds on any silent byte drift under an unchanged version id.
67
+ */
68
+ export declare const MEMORY_DISTILLER_CONTRACT_V1: LlmDistillerContract;
69
+ /**
70
+ * The A/B witness: which grouping lines differ between two contracts, by index — published beside
71
+ * readings so "only the wording moved" is a checkable statement about the prompts actually sent.
72
+ */
73
+ export declare function contractGroupingDiff(a: LlmDistillerContract | undefined, b: LlmDistillerContract | undefined): {
74
+ sameLineCount: boolean;
75
+ changedClauseIndexes: number[];
76
+ before: Array<string | null>;
77
+ after: Array<string | null>;
78
+ otherClausesIdentical: boolean;
79
+ writingPromptIdentical: boolean;
80
+ systemPromptsIdentical: boolean;
81
+ samplingIdentical: boolean;
82
+ };
83
+ /** The snapshot row shape the engine's `snapshotConsolidationCandidates` answers. */
84
+ export interface DistillerCandidate {
85
+ entry: MemoryEntry;
86
+ marked: boolean;
87
+ }
88
+ /** One JSON-only completion request (no streaming, no tools — the contract's whole call shape). */
89
+ export interface DistillerChatRequest {
90
+ system: string;
91
+ user: string;
92
+ maxTokens: number;
93
+ temperature: number;
94
+ }
95
+ export interface DistillerChatAnswer {
96
+ content: string;
97
+ /** The provider's finish reason; `"length"` marks a token-ceiling cut-off (retried, disclosed). */
98
+ finishReason?: string | null;
99
+ usage?: {
100
+ promptTokens?: number;
101
+ completionTokens?: number;
102
+ } | null;
103
+ /** The model id the provider REPORTS having served (audit anchor beside the requested id). */
104
+ model?: string | null;
105
+ }
106
+ export type DistillerChatFn = (req: DistillerChatRequest) => Promise<DistillerChatAnswer>;
107
+ /** True when the id is an ALIAS spelling (re-pointable upstream), refused wherever a model id is
108
+ * taken. A conservative SCREEN over the common alias grammars, not a full catalog — the honest
109
+ * direction is one-way: `true` ⇒ alias, while a `false` only means "not a spelling this screen
110
+ * knows". Screened: any id whose FINAL dash segment is `latest`/`default` regardless of how many
111
+ * segments the family name has (`chatgpt-4o-latest`, `claude-3-5-sonnet-latest`,
112
+ * `gemini-1.5-pro-latest`), plus the single-family `-chat` form (`deepseek-chat`, `qwen-chat` —
113
+ * the alias family upstream re-points have actually ridden). Multi-segment `-chat` ids are NOT
114
+ * screened on purpose: that suffix also names pinned chat variants of fixed weights
115
+ * (`llama-2-7b-chat`), and refusing those would reject explicit ids. */
116
+ export declare function isAliasModelId(model: string): boolean;
117
+ /**
118
+ * An OpenAI-compatible chat seat over an explicit endpoint. Screened at CONSTRUCTION (the
119
+ * bad-value loudness law): a missing key or an alias model id refuses with a code before any call
120
+ * is made — an alias can be re-pointed upstream and would move the driven model with no trace in
121
+ * the archived plan.
122
+ */
123
+ export declare function openAiCompatChatSeat(seat: {
124
+ baseUrl: string;
125
+ apiKey: string;
126
+ model: string;
127
+ }): DistillerChatFn;
128
+ export type ParsedJsonAnswer = {
129
+ ok: true;
130
+ value: unknown;
131
+ repaired: boolean;
132
+ } | {
133
+ ok: false;
134
+ error: string;
135
+ sample: string;
136
+ };
137
+ /**
138
+ * Parse ONE JSON object out of a model answer. Fenced and prefixed answers are tolerated (a
139
+ * formatting failure, not a distillation one) and the tolerance is COUNTED. A truncated answer is
140
+ * never salvaged — half a plan scored (or committed) as a whole plan is the failure mode this
141
+ * function exists to refuse.
142
+ */
143
+ export declare function parseJsonAnswer(text: unknown): ParsedJsonAnswer;
144
+ export interface PlanParseRepairs {
145
+ grouping: number;
146
+ writing: number;
147
+ groupingCalls: number;
148
+ writingCalls: number;
149
+ /** Calls whose answer was cut off at the token ceiling — a HARNESS parameter biting, named per
150
+ * call and never folded into a repair count it is not. */
151
+ lengthCapped: string[];
152
+ retries: number;
153
+ }
154
+ /**
155
+ * Format repairs per PHASE, re-derived from a plan's own archived transcript — one derivation
156
+ * produces the number (the grouping stage cannot be counted while the writing stage silently is
157
+ * not), and any reader can re-run it against the archive and get the same answer.
158
+ */
159
+ export declare function planParseRepairs(plan: {
160
+ minting?: {
161
+ transcript?: Array<{
162
+ label?: unknown;
163
+ answer?: unknown;
164
+ finishReason?: unknown;
165
+ }>;
166
+ };
167
+ } | undefined | null): PlanParseRepairs;
168
+ export interface SanitizedLlmGroups {
169
+ groups: Array<{
170
+ key: string;
171
+ intent: string;
172
+ members: Array<{
173
+ n: number;
174
+ id: string;
175
+ }>;
176
+ }>;
177
+ repairs: {
178
+ hallucinatedMembers: number;
179
+ duplicateMembers: number;
180
+ emptyGroups: number;
181
+ oversizeGroups: Array<{
182
+ key: string;
183
+ members: number;
184
+ cap: number;
185
+ }>;
186
+ nonIntegerMembers: number;
187
+ };
188
+ claimedIds: string[];
189
+ }
190
+ /**
191
+ * Turn the model's groups into a protocol-shaped product list, repairing only STRUCTURE and
192
+ * counting every repair:
193
+ *
194
+ * hallucinatedMembers — a number that is not in the candidate list at all;
195
+ * duplicateMembers — a number claimed by a second group (first claim, in the model's own
196
+ * group order, wins; the later claim is dropped);
197
+ * emptyGroups — a group left with no members after the two above;
198
+ * oversizeGroups — a group over `maxInputsPerProduct`. NOT split: chunking a group is a
199
+ * distillation decision, and making it on the model's behalf would put
200
+ * this module in the driver's seat. They ride on and the schedule reports
201
+ * them as structurally infeasible;
202
+ * nonIntegerMembers — a member reference that is not a strict integer. STRICT because
203
+ * `parseInt` is a silent truncator and the thing truncated is a ROW
204
+ * reference: "2foo"→2 and "1.5"→1 would each fold a DIFFERENT entry than
205
+ * the model named while every repair counter stayed at zero.
206
+ */
207
+ export declare function sanitizeLlmGroups(groups: unknown, { candidateIds, maxInputsPerProduct }: {
208
+ candidateIds: readonly string[];
209
+ maxInputsPerProduct?: number;
210
+ }): SanitizedLlmGroups;
211
+ export interface LlmConsolidationPlanProduct {
212
+ key: string;
213
+ intent: string;
214
+ name: string;
215
+ description: string;
216
+ type: "project" | "reference";
217
+ body: string;
218
+ inputIds: string[];
219
+ /** The committed rev of each input AT MINT TIME (id → rev). The replay filter refuses to fold an
220
+ * input whose committed rev has moved since the model read it — the product's body was written
221
+ * over the OLD bytes, and superseding the edited entry under it would suppress a newer value
222
+ * behind stale prose. Absent on plans minted before this field existed: those replay by id
223
+ * alone, exactly as they always did (the archived-readings compatibility arm). */
224
+ inputRevs?: Record<string, string>;
225
+ }
226
+ export interface LlmConsolidationPlan {
227
+ kind: "llm-consolidation-plan";
228
+ contractVersion: string;
229
+ model: string;
230
+ /** The endpoint the mint ran against, when the caller supplied one (audit locator only). */
231
+ baseUrl?: string;
232
+ mintedAt: string;
233
+ maxInputsPerProduct: number;
234
+ candidateCount: number;
235
+ products: LlmConsolidationPlanProduct[];
236
+ minting: {
237
+ calls: number;
238
+ groupingAttempts: number;
239
+ groupingParseRepairs: number;
240
+ parseRepairs: PlanParseRepairs;
241
+ repairs: SanitizedLlmGroups["repairs"];
242
+ writeFailures: Array<{
243
+ key: string;
244
+ members: number;
245
+ reason: string | null;
246
+ }>;
247
+ usage: {
248
+ promptTokens: number;
249
+ completionTokens: number;
250
+ };
251
+ prompts: {
252
+ grouping: string;
253
+ writingTemplate: string;
254
+ systems: {
255
+ grouping: string;
256
+ writing: string;
257
+ };
258
+ };
259
+ transcript: Array<{
260
+ label: string;
261
+ ms: number;
262
+ usage: DistillerChatAnswer["usage"];
263
+ finishReason: string | null;
264
+ model: string | null;
265
+ answer: string;
266
+ }>;
267
+ };
268
+ }
269
+ export type MintLlmConsolidationPlanResult = {
270
+ ok: true;
271
+ plan: LlmConsolidationPlan;
272
+ } | {
273
+ ok: false;
274
+ reason: string;
275
+ calls: LlmConsolidationPlan["minting"]["transcript"];
276
+ };
277
+ /**
278
+ * Mint a fold plan from a live model over one candidate snapshot. `candidates` is the snapshot
279
+ * shape the engine hands the driver (`{ entry, marked }`). Everything the model saw and everything
280
+ * it answered is returned inside the plan so the run can be re-read, re-scored and disputed from
281
+ * the archive alone.
282
+ */
283
+ export declare function mintLlmConsolidationPlan({ candidates, chat, model, baseUrl, maxInputsPerProduct, contract, onProgress, }: {
284
+ candidates: readonly DistillerCandidate[];
285
+ chat: DistillerChatFn;
286
+ /** The requested model id, recorded into the plan (audit anchor). Alias spellings refuse. */
287
+ model: string;
288
+ baseUrl?: string;
289
+ maxInputsPerProduct?: number;
290
+ contract?: LlmDistillerContract;
291
+ onProgress?: ((p: {
292
+ phase: "grouping";
293
+ groups: number;
294
+ claimed: number;
295
+ of: number;
296
+ } | {
297
+ phase: "writing";
298
+ done: number;
299
+ of: number;
300
+ }) => void) | null;
301
+ }): Promise<MintLlmConsolidationPlanResult>;
302
+ /** The distiller signature the drive consumes: `(candidates, snapshot, scope) -> proposal`.
303
+ * At runtime only `entry.id` is load-bearing for the replay filter — test/bench stubs that hand
304
+ * partial entry shapes are tolerated by the reads, the type states the engine's real snapshot.
305
+ * The drive consumes the proposal's FOLD face only (`products`; `scope` is the drive's own): a
306
+ * proposal carrying directed `intents` is REFUSED by the drive rather than silently narrowed —
307
+ * directed update/delete intents go through `commitConsolidationPlan` directly (see the drive's
308
+ * own doc for why a per-cycle forward is structurally impossible). */
309
+ export type ConsolidationDistillFn = (candidates: readonly DistillerCandidate[], snapshot: unknown, scope: string) => ConsolidationProposal | Promise<ConsolidationProposal>;
310
+ /**
311
+ * A minted plan replayed as a per-cycle distiller. Per cycle it filters each product's inputs down
312
+ * to the ids the snapshot is still offering — a product whose inputs have all been folded is empty
313
+ * and is the drive's termination signal. `supersede: true` rides on every input: an input
314
+ * attributed without the edge is provenance only, the row would stay active, and the run would
315
+ * read as "consolidation did nothing" for a reason on this side of the seam.
316
+ *
317
+ * This is the RUN-CACHE form the cost model depends on: one mint per run, this filter per cycle —
318
+ * re-minting per cycle would multiply the model bill by the cycle count for the same answer.
319
+ */
320
+ export declare function llmPlanDistiller(plan: {
321
+ products?: ReadonlyArray<Pick<LlmConsolidationPlanProduct, "name" | "description" | "type" | "body" | "inputIds"> & {
322
+ inputRevs?: Record<string, string>;
323
+ }>;
324
+ } | undefined | null): ConsolidationDistillFn;
325
+ export interface FuseSchedule<P> {
326
+ schedule: "next-fit-decreasing";
327
+ picked: P[];
328
+ targets: number;
329
+ ceiling: number;
330
+ deferred: number;
331
+ oversize: Array<{
332
+ name: string;
333
+ inputs: number;
334
+ cap: number;
335
+ }>;
336
+ }
337
+ /**
338
+ * One cycle's plan selection under the engine's supersession fuse.
339
+ *
340
+ * NEXT-FIT DECREASING: products in descending target count, stop at the first that does not fit.
341
+ * The missing backfill is the point, not an oversight: the ceiling is a FRACTION of the active set
342
+ * and every fold shrinks the active set, so a cycle that spends leftover budget on a small fold —
343
+ * one that would still fit later, at a lower ceiling — permanently lowers the ceiling every
344
+ * remaining large fold has to clear. Measured with the shipped 0.25 cap: a backfilling schedule
345
+ * dead-ends with two large digests permanently unfoldable while the same products converge when
346
+ * the large folds simply go first.
347
+ *
348
+ * `maxProductsPerRun` is honoured here too; a product whose input count exceeds
349
+ * `maxInputsPerProduct` can never be frozen at all and is reported structurally infeasible rather
350
+ * than retried forever.
351
+ */
352
+ export declare function scheduleUnderFuse<P extends {
353
+ name?: string;
354
+ inputs?: Array<{
355
+ id: string;
356
+ supersede?: boolean;
357
+ }>;
358
+ }>(products: readonly P[] | undefined, ceiling: number, { maxProductsPerRun, maxInputsPerProduct }?: {
359
+ maxProductsPerRun?: number;
360
+ maxInputsPerProduct?: number;
361
+ }): FuseSchedule<P>;
362
+ /** The engine face the drive consumes (MemoryEngine satisfies it structurally; tests may stub). */
363
+ export interface ConsolidationDriveEngine {
364
+ snapshotConsolidationCandidates(scope: string, opts?: {
365
+ force?: {
366
+ requestId: string;
367
+ };
368
+ full?: boolean;
369
+ }): Promise<{
370
+ cycleToken: string;
371
+ watermark?: unknown;
372
+ candidates: Array<{
373
+ entry: MemoryEntry;
374
+ marked: boolean;
375
+ }>;
376
+ }>;
377
+ commitConsolidationPlan(cycleToken: string, proposal: ConsolidationProposal, opts: {
378
+ requestId: string;
379
+ }): Promise<ConsolidationDriveReceipt>;
380
+ reconcileConsolidation(scope: string): Promise<{
381
+ replayed?: {
382
+ planId: string;
383
+ state: string;
384
+ } | null;
385
+ } | undefined | void>;
386
+ }
387
+ /** The commit receipt fields the drive reads (the engine's receipt carries more). */
388
+ export interface ConsolidationDriveReceipt {
389
+ planId?: string;
390
+ state?: string;
391
+ products?: {
392
+ frozen?: number;
393
+ applied?: number | null;
394
+ conflicts?: number | null;
395
+ refused?: Array<{
396
+ index: number;
397
+ reason: string;
398
+ }>;
399
+ };
400
+ }
401
+ export interface ConsolidationFoldState {
402
+ active: number;
403
+ superseded: number;
404
+ products: number;
405
+ }
406
+ export interface ConsolidationDriveCycleRow {
407
+ cycle: number;
408
+ activeSetSize: number;
409
+ ceiling: number;
410
+ candidates?: number;
411
+ /** How many of the cycle's served candidates carried a committed external-origin marker — the
412
+ * engine-served fact the fold law and the instruction hard gate key on (design/376 §2.1: a
413
+ * reading about the marked treatment must show the snapshot actually saw marked content, and a
414
+ * zero-marked run must show the zero). Absent only on the row of a snapshot that refused. */
415
+ markedCandidates?: number;
416
+ deferred?: number;
417
+ planId?: string;
418
+ state?: string;
419
+ applied?: number | null;
420
+ conflicts?: number | null;
421
+ refusedProducts?: Array<{
422
+ index: number;
423
+ reason: string;
424
+ }>;
425
+ reconciled?: {
426
+ planId: string;
427
+ state: string;
428
+ } | null;
429
+ note?: string;
430
+ refused?: string;
431
+ recovery?: {
432
+ attempted: boolean;
433
+ ok: boolean;
434
+ replayed: {
435
+ planId: string;
436
+ state: string;
437
+ } | null;
438
+ summary: string;
439
+ report?: unknown;
440
+ };
441
+ attempted: {
442
+ products: number;
443
+ targets: number;
444
+ };
445
+ committed: {
446
+ products: number;
447
+ superseded: number;
448
+ };
449
+ /** `committed`'s two flat mirrors — the drive-report projections read the row under these names
450
+ * as well as under `committed.*`; all three spellings are one store-delta fact. */
451
+ products: number;
452
+ targets: number;
453
+ }
454
+ export interface ConsolidationDriveResult {
455
+ /** A STORE fact: did anything actually fold. A refused first cycle answers false. */
456
+ ran: boolean;
457
+ schedule: "next-fit-decreasing";
458
+ cycles: ConsolidationDriveCycleRow[];
459
+ cycleCount: number;
460
+ productsCommitted: number;
461
+ entriesSuperseded: number;
462
+ productsAttempted: number;
463
+ engineRefusedProducts: Array<{
464
+ index: number;
465
+ reason: string;
466
+ }>;
467
+ converged: boolean;
468
+ foldState: {
469
+ before: ConsolidationFoldState;
470
+ after: ConsolidationFoldState;
471
+ };
472
+ stop?: {
473
+ reason: string;
474
+ refused?: boolean;
475
+ stalled?: boolean;
476
+ parked?: boolean;
477
+ exhausted?: boolean;
478
+ planId?: string;
479
+ fuseBlocked?: Array<{
480
+ name: string;
481
+ targets: number;
482
+ }>;
483
+ oversize?: Array<{
484
+ name: string;
485
+ inputs: number;
486
+ cap: number;
487
+ }>;
488
+ recovery?: unknown;
489
+ };
490
+ }
491
+ /** The engine's refusals carry a `code` and a `reasons` array; a bare `.message` throws half away. */
492
+ export declare function codedReason(err: unknown): string;
493
+ export interface DriveConsolidationOptions {
494
+ distill: ConsolidationDistillFn;
495
+ /** The fuse denominator AND every published count are store facts, never driver assumptions. */
496
+ readFoldState: () => Promise<ConsolidationFoldState> | ConsolidationFoldState;
497
+ options: {
498
+ supersedeRatioCap: number;
499
+ supersedeAbsoluteFloor: number;
500
+ maxProductsPerRun: number;
501
+ maxInputsPerProduct: number;
502
+ };
503
+ /** The ceiling arithmetic — pass the engine's `supersessionFuseCeiling` (single source). */
504
+ fuseCeilingOf: (activeSetSize: number, opts: {
505
+ supersedeRatioCap: number;
506
+ supersedeAbsoluteFloor: number;
507
+ }) => number;
508
+ requestIdPrefix?: string;
509
+ maxCycles?: number;
510
+ /**
511
+ * The snapshot step, injectable so a HOST scheduling policy (throttle waits, run-scoped force,
512
+ * busy recovery) wraps the verb without forking the loop. Default = the plain full snapshot.
513
+ * Anything it throws takes the loop's refusal arm exactly as the plain call would.
514
+ */
515
+ takeSnapshot?: (cycle: number) => ReturnType<ConsolidationDriveEngine["snapshotConsolidationCandidates"]>;
516
+ /** Observation hook after each cycle row closes against the store (run persistence seat). */
517
+ onCycle?: (row: ConsolidationDriveCycleRow) => void | Promise<void>;
518
+ }
519
+ /**
520
+ * Drive consolidation to its FIXPOINT: repeat snapshot → commit → reconcile until nothing is left
521
+ * to fold, the fuse can no longer admit the smallest remaining product, or the engine refuses.
522
+ *
523
+ * Why a loop is the honest shape: the supersession fuse caps ONE plan at a fraction of the active
524
+ * set (0.25 shipped), so a library that accumulated for many sessions cannot be folded by a single
525
+ * plan — the engine refuses that by design, and a driver that fired one plan and stopped would be
526
+ * converting a safety property into a failure report.
527
+ *
528
+ * Every snapshot asks `full: true`: snapshots are CHANGE-DRIVEN by default, so cycle 2 of a stable
529
+ * library would answer an EMPTY candidate set and strand most of the library unfolded. `full` is
530
+ * the protocol's own name for "re-distill what is already there", which is exactly what every
531
+ * cycle of a first consolidation is.
532
+ *
533
+ * WHAT WAS PROPOSED IS NEVER WHAT IS COUNTED: every per-cycle figure is a STORE delta —
534
+ * `readFoldState()` before and after each cycle, `committed` is the difference. Receipts are not
535
+ * enough (a `completed` receipt can carry per-product freeze refusals; a `conflict` receipt says
536
+ * how many applied but not which); the store is the only witness that cannot be off by a refusal.
537
+ */
538
+ export declare function driveConsolidationToFixpoint(engine: ConsolidationDriveEngine, scope: string, opts: DriveConsolidationOptions): Promise<ConsolidationDriveResult>;
539
+ /** A host snapshot policy (the injectable `takeSnapshot`) may classify its own stop as PARKED by
540
+ * throwing an error carrying this marker — e.g. a busy seat whose reconcile answered a conflict
541
+ * plan awaiting the host valve. The drive maps it onto the parked stop family. */
542
+ export declare const CONSOLIDATION_SNAPSHOT_PARKED: unique symbol;
543
+ /**
544
+ * A host ABORT marker: an error the injectable snapshot policy tags with this symbol is NOT an
545
+ * engine refusal — it is the host tearing the run down (a cancelled wait, a shutdown hook). The
546
+ * drive RETHROWS it instead of composing a refusal stop, so the caller's run account stays
547
+ * PENDING and the paid mint survives to the resume — folding a host abort into a terminal
548
+ * `refused` would silently discard a whole mint over a shutdown.
549
+ */
550
+ export declare const CONSOLIDATION_DRIVE_ABORT: unique symbol;