@sema-agent/core 5.57.0 → 5.59.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.
- package/CHANGELOG.md +96 -0
- package/dist/agents/cascade.d.ts +1 -1
- package/dist/agents/cumulative-stats.d.ts +1 -1
- package/dist/agents/observer.d.ts +2 -2
- package/dist/agents/peer-admission.d.ts +1 -1
- package/dist/agents/retain-ledger.d.ts +2 -2
- package/dist/agents/roster-store.d.ts +8 -8
- package/dist/agents/send-message-tool.d.ts +2 -2
- package/dist/agents/subagent-steps.d.ts +1 -1
- package/dist/agents/subagent.d.ts +13 -13
- package/dist/agents/team.d.ts +5 -5
- package/dist/agents/tool-filter.d.ts +2 -2
- package/dist/agents/verify.d.ts +1 -1
- package/dist/bench/metrics.d.ts +35 -35
- package/dist/brain/degrading.d.ts +1 -1
- package/dist/brain/errors.d.ts +3 -3
- package/dist/brain/reasoning.d.ts +2 -2
- package/dist/brain/repetition.d.ts +1 -1
- package/dist/brain/route-adjudicator.d.ts +8 -1
- package/dist/brain/route-adjudicator.js +8 -1
- package/dist/brain/status-sink.d.ts +2 -2
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/config/catalog.d.ts +5 -5
- package/dist/core/arg-summary.d.ts +4 -4
- package/dist/core/ask-class.d.ts +2 -2
- package/dist/core/ask-question.d.ts +1 -1
- package/dist/core/auto-compaction.d.ts +15 -15
- package/dist/core/auto-mode.d.ts +5 -5
- package/dist/core/background-agent-store.d.ts +20 -20
- package/dist/core/background-shell.d.ts +4 -4
- package/dist/core/checkpoint-store.d.ts +35 -27
- package/dist/core/context-edit.d.ts +1 -1
- package/dist/core/context-guard.d.ts +1 -1
- package/dist/core/exec-output-tail.d.ts +6 -6
- package/dist/core/file-snapshot-store.d.ts +8 -8
- package/dist/core/git-worktree-env.d.ts +3 -3
- package/dist/core/governance-codes.d.ts +37 -10
- package/dist/core/governance-codes.js +54 -1
- package/dist/core/hooks.d.ts +73 -33
- package/dist/core/hooks.js +87 -25
- package/dist/core/image-downsample.d.ts +1 -1
- package/dist/core/locked-config.d.ts +1 -1
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mailbox-store.d.ts +1 -1
- package/dist/core/mcp.d.ts +3 -3
- package/dist/core/memory-engine/consolidation-driver.d.ts +211 -0
- package/dist/core/memory-engine/consolidation-driver.js +427 -0
- package/dist/core/memory-engine/consolidation.d.ts +119 -3
- package/dist/core/memory-engine/consolidation.js +22 -1
- package/dist/core/memory-engine/data-plane.d.ts +1 -1
- package/dist/core/memory-engine/distiller.d.ts +550 -0
- package/dist/core/memory-engine/distiller.js +598 -0
- package/dist/core/memory-engine/dual-root.d.ts +1 -1
- package/dist/core/memory-engine/engine.d.ts +143 -10
- package/dist/core/memory-engine/engine.js +149 -23
- package/dist/core/memory-engine/file-backend.d.ts +14 -2
- package/dist/core/memory-engine/file-backend.js +3 -0
- package/dist/core/memory-engine/index.d.ts +6 -3
- package/dist/core/memory-engine/index.js +4 -2
- package/dist/core/memory-engine/layout.js +20 -6
- package/dist/core/memory-engine/origin-clearance.d.ts +1 -1
- package/dist/core/memory-engine/scope-contract.d.ts +4 -4
- package/dist/core/memory-engine/sync-client.d.ts +16 -16
- package/dist/core/memory-engine/sync.d.ts +4 -4
- package/dist/core/memory-engine/types.d.ts +17 -0
- package/dist/core/memory-recall.d.ts +1 -1
- package/dist/core/memory.d.ts +2 -2
- package/dist/core/permission-rule-consent.d.ts +185 -36
- package/dist/core/permission-rule-consent.js +219 -44
- package/dist/core/permission-rule-model.d.ts +235 -31
- package/dist/core/permission-rule-model.js +105 -35
- package/dist/core/permission-rules.d.ts +9 -9
- package/dist/core/remote-env.d.ts +8 -8
- package/dist/core/roles.d.ts +3 -3
- package/dist/core/roles.js +1 -0
- package/dist/core/runner/assemble-result.d.ts +2 -2
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/memory-consolidation-driver.d.ts +49 -0
- package/dist/core/runner/memory-consolidation-driver.js +60 -0
- package/dist/core/runner/memory-consolidation.d.ts +1 -1
- package/dist/core/runner/prepare-config-doors.d.ts +3 -3
- package/dist/core/runner/prepare-task.d.ts +21 -21
- package/dist/core/runner/prepare-task.js +24 -17
- package/dist/core/runner/prepare-workspace-restore.d.ts +2 -2
- package/dist/core/runner/runtask.d.ts +11 -11
- package/dist/core/runner/runtask.js +4 -4
- package/dist/core/runner/session-rule-policy.d.ts +1 -1
- package/dist/core/runner/teardown-bounded.d.ts +1 -1
- package/dist/core/runner/tool-disclosure.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +11 -11
- package/dist/core/scheduler.d.ts +5 -5
- package/dist/core/secret-env.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/session-policy-store.d.ts +2 -2
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +3 -3
- package/dist/core/session.d.ts +1 -1
- package/dist/core/shutdown-debug.d.ts +2 -2
- package/dist/core/side-query.d.ts +2 -2
- package/dist/core/spec-contract.d.ts +1 -1
- package/dist/core/store-contracts/contract-harness.d.ts +2 -2
- package/dist/core/store-contracts/contract-kit-version.d.ts +2 -2
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +1 -1
- package/dist/core/store-contracts/mailbox-store-contract.js +1 -1
- package/dist/core/task-notification.d.ts +5 -5
- package/dist/core/task-registry-agent.d.ts +12 -12
- package/dist/core/task-registry-monitor.d.ts +1 -1
- package/dist/core/task-registry-shared.d.ts +41 -41
- package/dist/core/task-registry.d.ts +12 -12
- package/dist/core/tool-detach.d.ts +2 -2
- package/dist/core/tool-errors.d.ts +3 -3
- package/dist/core/tool-policy.d.ts +113 -28
- package/dist/core/tool-policy.js +80 -1
- package/dist/core/tool-result-budget.d.ts +1 -1
- package/dist/core/tool-result-store.d.ts +2 -2
- package/dist/core/tools.d.ts +1 -1
- package/dist/core/trace.d.ts +26 -23
- package/dist/core/types.d.ts +164 -86
- package/dist/core/types.js +4 -3
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +7 -7
- package/dist/core/wiring-manifest.d.ts +5 -5
- package/dist/core/workflow-journal-store.d.ts +14 -14
- package/dist/core/workflow-run-store-contract.d.ts +1 -1
- package/dist/core/workflow-run-store-contract.js +1 -1
- package/dist/core/workflow-run-store.d.ts +4 -4
- package/dist/engine/compaction/compaction.d.ts +3 -3
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/execution-env/kill-tree.d.ts +1 -1
- package/dist/engine/execution-env/node-execution-env.d.ts +8 -8
- package/dist/engine/harness/agent-harness.d.ts +6 -6
- package/dist/engine/harness/messages.d.ts +1 -1
- package/dist/engine/harness/types.d.ts +10 -10
- package/dist/engine/llm/types.d.ts +14 -14
- package/dist/engine/loop/agent-loop.d.ts +3 -3
- package/dist/engine/loop/types.d.ts +4 -4
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/import-validate.d.ts +1 -1
- package/dist/engine/session/log-digest.d.ts +1 -1
- package/dist/engine/session/memory-repo.d.ts +2 -2
- package/dist/engine/session/session.d.ts +4 -4
- package/dist/fixtures/index.d.ts +4 -4
- package/dist/index.d.ts +6 -5
- package/dist/index.js +5 -4
- package/dist/orchestration/goal.d.ts +1 -1
- package/dist/orchestration/run-spec.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +12 -12
- package/dist/orchestration/workflow-governance.d.ts +4 -4
- package/dist/orchestration/workflow-observe.d.ts +1 -1
- package/dist/orchestration/workflow-script-runner.d.ts +1 -1
- package/dist/orchestration/workflow-script-store.d.ts +9 -9
- package/dist/orchestration/workflow-size-guideline.d.ts +1 -1
- package/dist/orchestration/workflow-types.d.ts +5 -5
- package/dist/orchestration/workflow.d.ts +10 -10
- package/dist/prompt-assembly/artifact-store.d.ts +1 -1
- package/dist/prompt-assembly/artifact.d.ts +1 -1
- package/dist/prompt-assembly/assemble.d.ts +1 -1
- package/dist/prompt-assembly/composer.d.ts +2 -2
- package/dist/prompt-assembly/epoch.d.ts +2 -2
- package/dist/prompt-assembly/event-registry.d.ts +1 -1
- package/dist/prompt-assembly/explain.d.ts +3 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +1 -1
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -4
- package/dist/prompt-assembly/types.d.ts +12 -12
- package/dist/prompts/coordinator.d.ts +1 -1
- package/dist/prompts/default.d.ts +8 -8
- package/dist/prompts/simple-sections.d.ts +3 -3
- package/dist/prompts/supervisor.d.ts +2 -2
- package/dist/scenarios/full-body.d.ts +3 -3
- package/dist/scenarios/scenario-registry.d.ts +1 -1
- package/dist/stores/cc/sidecar-transcript.d.ts +3 -3
- package/dist/stores/file/fs-atomic.d.ts +2 -2
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/session-store.d.ts +2 -2
- package/dist/stores/file/workflow-journal-store.d.ts +4 -4
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/encoding.d.ts +4 -4
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-pdf.d.ts +1 -1
- package/dist/tools/fs/fs-shared.d.ts +6 -6
- package/dist/tools/fs/index.d.ts +2 -2
- package/dist/tools/fs/notebook.d.ts +1 -1
- package/dist/tools/fs/pdf.d.ts +1 -1
- package/dist/tools/fs/read-deny.d.ts +1 -1
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +2 -2
- package/dist/tools/monitor.d.ts +3 -3
- package/dist/tools/task-list.d.ts +2 -2
- package/dist/tools/web.d.ts +4 -4
- package/dist/tools/worktree.d.ts +5 -5
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +1826 -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;
|