@deepstrike/sdk 0.2.62 → 0.2.64
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/LICENSE +106 -0
- package/dist/index.d.ts +8 -4
- package/dist/index.js +6 -1
- package/dist/providers/anthropic.d.ts +5 -1
- package/dist/providers/anthropic.js +15 -0
- package/dist/providers/gemini.d.ts +4 -1
- package/dist/providers/gemini.js +15 -1
- package/dist/providers/ollama.d.ts +4 -1
- package/dist/providers/ollama.js +7 -0
- package/dist/providers/openai-responses.d.ts +4 -1
- package/dist/providers/openai-responses.js +16 -0
- package/dist/providers/openai.d.ts +4 -1
- package/dist/providers/openai.js +13 -0
- package/dist/providers/request-plan.d.ts +40 -0
- package/dist/providers/request-plan.js +61 -0
- package/dist/runtime/execution-evidence.d.ts +116 -0
- package/dist/runtime/execution-evidence.js +51 -0
- package/dist/runtime/kernel-step.d.ts +2 -0
- package/dist/runtime/kernel-step.js +2 -2
- package/dist/runtime/runner.d.ts +24 -0
- package/dist/runtime/runner.js +165 -6
- package/dist/runtime/session-log.d.ts +20 -3
- package/dist/runtime/session-log.js +144 -0
- package/dist/runtime/session-repair.d.ts +8 -1
- package/dist/runtime/session-repair.js +10 -0
- package/dist/types.d.ts +32 -0
- package/package.json +3 -2
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P4 (0.2.64 Execution Evidence Plane): the host-side object model connecting a kernel-minted
|
|
3
|
+
* effect to the real provider execution it drove — ModelInvocation / ProviderAttempt /
|
|
4
|
+
* ResolvedProviderRoute / UsageAccountingPolicy. Everything here is L2 host evidence
|
|
5
|
+
* (B7): it lands in SessionLog for cross-verification against the journal (C6/C8) and is
|
|
6
|
+
* NEVER fed back as kernel input (B4/DEC-2 discipline: wall-clock and wire facts stay host-side).
|
|
7
|
+
*
|
|
8
|
+
* Kernel ABI is untouched — the kernel projection of an invocation outcome remains the
|
|
9
|
+
* existing ProviderCompleted/HostEffectFailure shapes (D2).
|
|
10
|
+
*/
|
|
11
|
+
import type { ProviderUsage, ProviderWireEvidence, UsageEvent } from "../types.js";
|
|
12
|
+
import { type NormalizedProviderUsage, type ResolvedProviderRoute } from "../providers/request-plan.js";
|
|
13
|
+
/** Canonical stop-reason vocabulary already carried on the wire usage frame (types.ts). */
|
|
14
|
+
export type CanonicalStopReason = NonNullable<UsageEvent["stopReason"]>;
|
|
15
|
+
/**
|
|
16
|
+
* P4 §1.1: one logical model call = the fact-connected chain of CallProvider effects the
|
|
17
|
+
* kernel walked to obtain one turn of model output. Derived identity, zero minting:
|
|
18
|
+
* `invocationId` IS the first effect's effect_id. Authority = journal; the SessionLog
|
|
19
|
+
* projection (`llm_completed.invocation_id`) is evidence only.
|
|
20
|
+
*/
|
|
21
|
+
export interface ModelInvocation {
|
|
22
|
+
invocationId: string;
|
|
23
|
+
turn: number;
|
|
24
|
+
/** Every effect_id on the chain, in order. Length 1 = first attempt succeeded. */
|
|
25
|
+
effectChain: string[];
|
|
26
|
+
outcome?: InvocationOutcome;
|
|
27
|
+
}
|
|
28
|
+
/** P4 §1.4: the invocation's terminal projection. */
|
|
29
|
+
export interface InvocationOutcome {
|
|
30
|
+
invocationId: string;
|
|
31
|
+
/** The effect the kernel adopted as the outcome (the successful one). */
|
|
32
|
+
selectedEffectId: string;
|
|
33
|
+
stopReason?: CanonicalStopReason;
|
|
34
|
+
/** Absent on a failed chain (nothing settled). */
|
|
35
|
+
settlement?: ModelUsageSettlement;
|
|
36
|
+
}
|
|
37
|
+
export type ProviderAttemptStatus = "success" | "transport_exhausted" | "aborted" | "rejected";
|
|
38
|
+
/**
|
|
39
|
+
* P4 §1.2: one effect's execution against one route, one physical attempt. The kernel-minted
|
|
40
|
+
* `effectId` is the primary key (H7 — no parallel id minting). Transport-ladder rungs are
|
|
41
|
+
* summarized as a count plus the final error class; rung-level evidence belongs to adapter
|
|
42
|
+
* debug logs, not SessionLog.
|
|
43
|
+
*/
|
|
44
|
+
export interface ProviderAttempt {
|
|
45
|
+
effectId: string;
|
|
46
|
+
/** Failover sequence within one effect execution (1-based). Always 1 today (P4 §0.2). */
|
|
47
|
+
attemptSeq: number;
|
|
48
|
+
route: ResolvedProviderRoute;
|
|
49
|
+
/** → ProviderRequestPlan.fingerprint (G2). */
|
|
50
|
+
requestFingerprint: string;
|
|
51
|
+
status: ProviderAttemptStatus;
|
|
52
|
+
transportRungs: number;
|
|
53
|
+
/** classifyProviderError's class, never the raw vendor text (B1 spirit). */
|
|
54
|
+
lastErrorClass?: string;
|
|
55
|
+
/** Host wall-clock, pure evidence, never kernel input (DEC-2 discipline). */
|
|
56
|
+
startedAtMs: number;
|
|
57
|
+
finishedAtMs: number;
|
|
58
|
+
/** Full measurement fields (P4 §2); only the settlement crosses the kernel boundary (B4). */
|
|
59
|
+
usage?: NormalizedProviderUsage;
|
|
60
|
+
wireEvidence?: ProviderWireEvidence;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The SessionLog wire payload of a ProviderAttempt (P4 §3): the §1.2 fields flattened into
|
|
64
|
+
* the event, snake_case per SessionLog convention. Nested objects keep their native shape
|
|
65
|
+
* (same convention as `prompt_measured.measurement`).
|
|
66
|
+
*/
|
|
67
|
+
export interface ProviderAttemptRecord {
|
|
68
|
+
effect_id: string;
|
|
69
|
+
attempt_seq: number;
|
|
70
|
+
route: ResolvedProviderRoute;
|
|
71
|
+
request_fingerprint: string;
|
|
72
|
+
status: ProviderAttemptStatus;
|
|
73
|
+
transport_rungs: number;
|
|
74
|
+
last_error_class?: string;
|
|
75
|
+
started_at_ms: number;
|
|
76
|
+
finished_at_ms: number;
|
|
77
|
+
usage?: NormalizedProviderUsage;
|
|
78
|
+
wire_evidence?: ProviderWireEvidence;
|
|
79
|
+
/** P4 §2.1: the accounting policy this attempt's settlement was/will be derived with —
|
|
80
|
+
* pinned on the attempt so settlement is deterministically recomputable from
|
|
81
|
+
* (measurement, policy_id). */
|
|
82
|
+
accounting_policy_id?: string;
|
|
83
|
+
}
|
|
84
|
+
export declare function providerAttemptToRecord(attempt: ProviderAttempt, accountingPolicyId?: string): ProviderAttemptRecord;
|
|
85
|
+
/**
|
|
86
|
+
* P4 §2: the only two numbers that cross the kernel boundary (B4). Field names match the
|
|
87
|
+
* existing ResolveEffect wire shape — this is what the runner already feeds the kernel as
|
|
88
|
+
* `observed_input_tokens` / `observed_output_tokens`.
|
|
89
|
+
*/
|
|
90
|
+
export interface ModelUsageSettlement {
|
|
91
|
+
observed_input_tokens: number;
|
|
92
|
+
observed_output_tokens: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* P4 §2.1: the named, pinnable, replayable policy turning a measurement into a settlement.
|
|
96
|
+
* `settle` must be a pure function of the measurement — given (usage, policyId) any auditor
|
|
97
|
+
* recomputes the identical settlement.
|
|
98
|
+
*/
|
|
99
|
+
export interface UsageAccountingPolicy {
|
|
100
|
+
policyId: string;
|
|
101
|
+
settle(usage: NormalizedProviderUsage): ModelUsageSettlement;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The default policy = today's implicit runner behavior exactly (full input footprint + full
|
|
105
|
+
* output footprint — the two numbers the runner has always fed `observed_*`). P4 changes no
|
|
106
|
+
* default numbers; it only makes the conversion a named object. The date stamp is the
|
|
107
|
+
* policy's identity: any future semantics change MUST ship under a new policyId.
|
|
108
|
+
*/
|
|
109
|
+
export declare const FULL_FOOTPRINT_USAGE_ACCOUNTING_POLICY: UsageAccountingPolicy;
|
|
110
|
+
/**
|
|
111
|
+
* Defensive measurement assembly for the attempt evidence path: an invalid frame (cache
|
|
112
|
+
* subsets exceeding input, etc.) degrades to NO measurement instead of breaking the run —
|
|
113
|
+
* evidence is never worth a run failure, and the settlement falls back to the raw counts.
|
|
114
|
+
* Telemetry fields normalizeProviderUsage drops are re-attached so `usage` stays full-field.
|
|
115
|
+
*/
|
|
116
|
+
export declare function tryNormalizeProviderUsage(usage: ProviderUsage): NormalizedProviderUsage | undefined;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { normalizeProviderUsage, } from "../providers/request-plan.js";
|
|
2
|
+
export function providerAttemptToRecord(attempt, accountingPolicyId) {
|
|
3
|
+
return {
|
|
4
|
+
effect_id: attempt.effectId,
|
|
5
|
+
attempt_seq: attempt.attemptSeq,
|
|
6
|
+
route: attempt.route,
|
|
7
|
+
request_fingerprint: attempt.requestFingerprint,
|
|
8
|
+
status: attempt.status,
|
|
9
|
+
transport_rungs: attempt.transportRungs,
|
|
10
|
+
...(attempt.lastErrorClass !== undefined ? { last_error_class: attempt.lastErrorClass } : {}),
|
|
11
|
+
started_at_ms: attempt.startedAtMs,
|
|
12
|
+
finished_at_ms: attempt.finishedAtMs,
|
|
13
|
+
...(attempt.usage !== undefined ? { usage: attempt.usage } : {}),
|
|
14
|
+
...(attempt.wireEvidence !== undefined ? { wire_evidence: attempt.wireEvidence } : {}),
|
|
15
|
+
...(accountingPolicyId !== undefined ? { accounting_policy_id: accountingPolicyId } : {}),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The default policy = today's implicit runner behavior exactly (full input footprint + full
|
|
20
|
+
* output footprint — the two numbers the runner has always fed `observed_*`). P4 changes no
|
|
21
|
+
* default numbers; it only makes the conversion a named object. The date stamp is the
|
|
22
|
+
* policy's identity: any future semantics change MUST ship under a new policyId.
|
|
23
|
+
*/
|
|
24
|
+
export const FULL_FOOTPRINT_USAGE_ACCOUNTING_POLICY = {
|
|
25
|
+
policyId: "deepstrike.full-footprint@2026-09-15",
|
|
26
|
+
settle(usage) {
|
|
27
|
+
return {
|
|
28
|
+
observed_input_tokens: usage.inputTokens,
|
|
29
|
+
observed_output_tokens: usage.outputTokens,
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Defensive measurement assembly for the attempt evidence path: an invalid frame (cache
|
|
35
|
+
* subsets exceeding input, etc.) degrades to NO measurement instead of breaking the run —
|
|
36
|
+
* evidence is never worth a run failure, and the settlement falls back to the raw counts.
|
|
37
|
+
* Telemetry fields normalizeProviderUsage drops are re-attached so `usage` stays full-field.
|
|
38
|
+
*/
|
|
39
|
+
export function tryNormalizeProviderUsage(usage) {
|
|
40
|
+
try {
|
|
41
|
+
const normalized = normalizeProviderUsage(usage);
|
|
42
|
+
return {
|
|
43
|
+
...normalized,
|
|
44
|
+
...(usage.cacheTelemetryStatus !== undefined ? { cacheTelemetryStatus: usage.cacheTelemetryStatus } : {}),
|
|
45
|
+
...(usage.cacheTelemetrySource !== undefined ? { cacheTelemetrySource: usage.cacheTelemetrySource } : {}),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { EntropySample, Message, RenderedContext, TaskUpdate, ToolCall, ToolResult, ToolSchema } from "../types.js";
|
|
2
2
|
import type { SkillMetadata } from "../skills/loader.js";
|
|
3
3
|
import type { RollbackReason } from "./session-log.js";
|
|
4
|
+
export declare const CANONICAL_CONTENT_PARTS_PREFIX = "[[deepstrike-content-parts]]";
|
|
4
5
|
export declare function encodeCanonicalContentParts(parts: unknown[]): string;
|
|
6
|
+
export declare function decodeCanonicalContentParts(content: string): Array<Record<string, unknown>> | undefined;
|
|
5
7
|
export interface PaceDecision {
|
|
6
8
|
action: "continue" | "sleep" | "stop";
|
|
7
9
|
delayMs?: number;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const CANONICAL_CONTENT_PARTS_PREFIX = "[[deepstrike-content-parts]]";
|
|
1
|
+
export const CANONICAL_CONTENT_PARTS_PREFIX = "[[deepstrike-content-parts]]";
|
|
2
2
|
export function encodeCanonicalContentParts(parts) {
|
|
3
3
|
return `${CANONICAL_CONTENT_PARTS_PREFIX}${Buffer.from(JSON.stringify(parts)).toString("base64url")}`;
|
|
4
4
|
}
|
|
5
|
-
function decodeCanonicalContentParts(content) {
|
|
5
|
+
export function decodeCanonicalContentParts(content) {
|
|
6
6
|
if (!content.startsWith(CANONICAL_CONTENT_PARTS_PREFIX))
|
|
7
7
|
return undefined;
|
|
8
8
|
try {
|
package/dist/runtime/runner.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare function stableSemanticArchiveName(effectId: string): string;
|
|
|
13
13
|
import { type SubAgentOrchestrator } from "./sub-agent-orchestrator.js";
|
|
14
14
|
import { type ReducerRegistry } from "./reducers.js";
|
|
15
15
|
import { type GovernancePolicy } from "../governance.js";
|
|
16
|
+
import { type UsageAccountingPolicy } from "./execution-evidence.js";
|
|
16
17
|
import { type NativeOsProfile, type OsProfileId, type SignalPolicy } from "./os-profile.js";
|
|
17
18
|
import { PayloadStore } from "./payload-store.js";
|
|
18
19
|
import type { BackgroundTaskErrorHandler } from "./reliability.js";
|
|
@@ -176,6 +177,12 @@ export interface RuntimeOptions {
|
|
|
176
177
|
signalPolicy?: SignalPolicy;
|
|
177
178
|
/** Provider-envelope overhead plus output and safety reserves journaled before start. */
|
|
178
179
|
promptBudget?: PromptBudget;
|
|
180
|
+
/**
|
|
181
|
+
* P4-S2: the measurement→settlement conversion policy. Absent ⇒ the default full-footprint
|
|
182
|
+
* policy — byte-identical numbers to what the runner has always fed `observed_*`; the policy
|
|
183
|
+
* only makes the conversion named, pinnable on `provider_attempt`, and replayable.
|
|
184
|
+
*/
|
|
185
|
+
usageAccountingPolicy?: UsageAccountingPolicy;
|
|
179
186
|
/** Stable replayable context behavior; SDK ratios are normalized to integer ppm on the ABI wire. */
|
|
180
187
|
contextPolicy?: ContextPolicyOverrides;
|
|
181
188
|
/** Deterministic DAG scheduling policy installed atomically through ConfigureRun. */
|
|
@@ -403,6 +410,16 @@ export declare class RuntimeRunner {
|
|
|
403
410
|
private readonly composedSystemPrompt;
|
|
404
411
|
/** H1.2: present only when `opts.nudges` is non-empty; else null and the append funnel is untouched. */
|
|
405
412
|
private readonly nudgeEngine;
|
|
413
|
+
/** P4-S1: the run's resolved provider route, assembled once at construction (P4 §0.2 — the
|
|
414
|
+
* provider is fixed for the run today; every attempt references this same route object). */
|
|
415
|
+
private readonly providerRoute;
|
|
416
|
+
/** P4-S2: measurement→settlement policy; default = the exact implicit behavior (numbers unchanged). */
|
|
417
|
+
private readonly usageAccountingPolicy;
|
|
418
|
+
/** P4 §1.1: the active invocation's derived identity = its chain's FIRST effect_id. Tracked
|
|
419
|
+
* across kernel-driven provider retries (a provider_error commit arms `providerRetryPending`;
|
|
420
|
+
* the next call_provider adopts the pending invocation instead of opening a new one). */
|
|
421
|
+
private activeProviderInvocationId;
|
|
422
|
+
private providerRetryPending;
|
|
406
423
|
constructor(opts: RuntimeOptions);
|
|
407
424
|
/** Host configuration (for coordinator / sub-agent spawn). */
|
|
408
425
|
get hostOptions(): RuntimeOptions;
|
|
@@ -412,6 +429,13 @@ export declare class RuntimeRunner {
|
|
|
412
429
|
private commitKernelAction;
|
|
413
430
|
private startKernelAgent;
|
|
414
431
|
private payloadStore;
|
|
432
|
+
/**
|
|
433
|
+
* P4-S1 (G1): land one provider_attempt evidence record per effect execution. Pure host
|
|
434
|
+
* evidence (B7) — appended AFTER the transport fact exists (success/failure/abort), never
|
|
435
|
+
* consulted for kernel input. The accounting policy id pins only when a measurement exists,
|
|
436
|
+
* so (usage, policy_id) deterministically recomputes the settlement that crossed the wire.
|
|
437
|
+
*/
|
|
438
|
+
private appendProviderAttempt;
|
|
415
439
|
private persistMemoryToStore;
|
|
416
440
|
private retrieveMemoryFromStore;
|
|
417
441
|
/**
|
package/dist/runtime/runner.js
CHANGED
|
@@ -24,7 +24,8 @@ import { extractJsonValue, schemaInstruction, schemaRetryInstruction, validateAg
|
|
|
24
24
|
import { resolveReducer } from "./reducers.js";
|
|
25
25
|
import { loopInstruction, classifyInstruction, judgeGoal, dependencyOutputsNote, extractClassifyBranch, extractJudgeWinner, } from "./workflow-control-flow.js";
|
|
26
26
|
import { governancePolicyToKernelEvent, governanceFilterSchema } from "../governance.js";
|
|
27
|
-
import { createProviderRequestPlanForProvider, estimateProviderPromptTokens, measurementForPlan, recordPromptMeasurement, } from "../providers/request-plan.js";
|
|
27
|
+
import { createProviderRequestPlanForProvider, estimateProviderPromptTokens, measurementForPlan, recordPromptMeasurement, resolveProviderRoute, } from "../providers/request-plan.js";
|
|
28
|
+
import { FULL_FOOTPRINT_USAGE_ACCOUNTING_POLICY, providerAttemptToRecord, tryNormalizeProviderUsage, } from "./execution-evidence.js";
|
|
28
29
|
import { kernelObservationToSessionEvent } from "./kernel-event-log.js";
|
|
29
30
|
import { assertNativeProfile } from "./os-profile.js";
|
|
30
31
|
import { PayloadStore } from "./payload-store.js";
|
|
@@ -164,6 +165,16 @@ export class RuntimeRunner {
|
|
|
164
165
|
composedSystemPrompt;
|
|
165
166
|
/** H1.2: present only when `opts.nudges` is non-empty; else null and the append funnel is untouched. */
|
|
166
167
|
nudgeEngine;
|
|
168
|
+
/** P4-S1: the run's resolved provider route, assembled once at construction (P4 §0.2 — the
|
|
169
|
+
* provider is fixed for the run today; every attempt references this same route object). */
|
|
170
|
+
providerRoute;
|
|
171
|
+
/** P4-S2: measurement→settlement policy; default = the exact implicit behavior (numbers unchanged). */
|
|
172
|
+
usageAccountingPolicy;
|
|
173
|
+
/** P4 §1.1: the active invocation's derived identity = its chain's FIRST effect_id. Tracked
|
|
174
|
+
* across kernel-driven provider retries (a provider_error commit arms `providerRetryPending`;
|
|
175
|
+
* the next call_provider adopts the pending invocation instead of opening a new one). */
|
|
176
|
+
activeProviderInvocationId;
|
|
177
|
+
providerRetryPending = false;
|
|
167
178
|
constructor(opts) {
|
|
168
179
|
this.opts = opts;
|
|
169
180
|
const schemaAttempts = opts.workflowSchemaValidationAttempts ?? 2;
|
|
@@ -175,6 +186,8 @@ export class RuntimeRunner {
|
|
|
175
186
|
if (opts.memoryPolicy)
|
|
176
187
|
memoryPolicyToKernel(opts.memoryPolicy);
|
|
177
188
|
this.composedSystemPrompt = composeSystemPrompt(opts.systemPrompt, opts.instructions);
|
|
189
|
+
this.providerRoute = resolveProviderRoute(opts.provider);
|
|
190
|
+
this.usageAccountingPolicy = opts.usageAccountingPolicy ?? FULL_FOOTPRINT_USAGE_ACCOUNTING_POLICY;
|
|
178
191
|
if (opts.enableDiagnosticsDashboard) {
|
|
179
192
|
const originalAppend = opts.sessionLog.append.bind(opts.sessionLog);
|
|
180
193
|
opts.sessionLog.append = async (sessionId, event) => {
|
|
@@ -230,6 +243,18 @@ export class RuntimeRunner {
|
|
|
230
243
|
this.fallbackPayloadStore ??= new PayloadStore();
|
|
231
244
|
return this.fallbackPayloadStore;
|
|
232
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* P4-S1 (G1): land one provider_attempt evidence record per effect execution. Pure host
|
|
248
|
+
* evidence (B7) — appended AFTER the transport fact exists (success/failure/abort), never
|
|
249
|
+
* consulted for kernel input. The accounting policy id pins only when a measurement exists,
|
|
250
|
+
* so (usage, policy_id) deterministically recomputes the settlement that crossed the wire.
|
|
251
|
+
*/
|
|
252
|
+
async appendProviderAttempt(sessionId, attempt) {
|
|
253
|
+
await this.opts.sessionLog.append(sessionId, {
|
|
254
|
+
kind: "provider_attempt",
|
|
255
|
+
...providerAttemptToRecord(attempt, attempt.usage ? this.usageAccountingPolicy.policyId : undefined),
|
|
256
|
+
});
|
|
257
|
+
}
|
|
233
258
|
async persistMemoryToStore(memory, agentId) {
|
|
234
259
|
if (!this.opts.memoryStore)
|
|
235
260
|
throw new Error("memory persistence requires memoryStore");
|
|
@@ -754,6 +779,7 @@ export class RuntimeRunner {
|
|
|
754
779
|
goal: `workflow:${spec.nodes.length} nodes`,
|
|
755
780
|
criteria: [],
|
|
756
781
|
agent_id: this.opts.agentId,
|
|
782
|
+
route: this.providerRoute,
|
|
757
783
|
});
|
|
758
784
|
await this.initializeWorkflowKernel(sessionId, runId, groupBudgetScope);
|
|
759
785
|
}
|
|
@@ -1204,6 +1230,7 @@ export class RuntimeRunner {
|
|
|
1204
1230
|
agent_id: this.opts.agentId,
|
|
1205
1231
|
system_prompt: this.composedSystemPrompt,
|
|
1206
1232
|
...(attachments ? { attachments } : {}),
|
|
1233
|
+
route: this.providerRoute,
|
|
1207
1234
|
});
|
|
1208
1235
|
}
|
|
1209
1236
|
yield* this.execute(req.sessionId, req.goal, req.criteria ?? [], req.extensions, prior.length > 0 ? prior : undefined, midRun, attachments, runId);
|
|
@@ -1233,7 +1260,10 @@ export class RuntimeRunner {
|
|
|
1233
1260
|
yield* this.execute(sessionId, start.goal, start.criteria, extensions, events, true, start.attachments, start.run_id);
|
|
1234
1261
|
}
|
|
1235
1262
|
/** Execute a kernel-owned approval effect and return the correlated decision lists. */
|
|
1236
|
-
async resolveApprovalRequests(requests, runtime, sessionId
|
|
1263
|
+
async resolveApprovalRequests(requests, runtime, sessionId,
|
|
1264
|
+
/** P3-S2 (G4): the request_approval effect's id — pinned on the denial's tool_completed
|
|
1265
|
+
* so the denial evidence joins the journal effect chain like an executed tool's does. */
|
|
1266
|
+
effectId) {
|
|
1237
1267
|
const approved = [];
|
|
1238
1268
|
const denied = [];
|
|
1239
1269
|
const events = [];
|
|
@@ -1306,6 +1336,7 @@ export class RuntimeRunner {
|
|
|
1306
1336
|
error_kind: "governance_denied",
|
|
1307
1337
|
content: { blocks: [{ type: "text", text: `permission denied: ${denyReason}` }] },
|
|
1308
1338
|
}],
|
|
1339
|
+
...(effectId !== undefined ? { effect_id: effectId } : {}),
|
|
1309
1340
|
});
|
|
1310
1341
|
}
|
|
1311
1342
|
}
|
|
@@ -1319,6 +1350,8 @@ export class RuntimeRunner {
|
|
|
1319
1350
|
this.pendingPageOutArchives = [];
|
|
1320
1351
|
this.activePageOutArchive = undefined;
|
|
1321
1352
|
this.currentSessionId = sessionId;
|
|
1353
|
+
this.activeProviderInvocationId = undefined;
|
|
1354
|
+
this.providerRetryPending = false;
|
|
1322
1355
|
if (this.opts.enableDiagnosticsDashboard) {
|
|
1323
1356
|
this.dashboard = new KernelPrimitivesDashboard(sessionId);
|
|
1324
1357
|
}
|
|
@@ -1557,6 +1590,18 @@ export class RuntimeRunner {
|
|
|
1557
1590
|
break;
|
|
1558
1591
|
if (action.kind === "call_provider") {
|
|
1559
1592
|
const providerEffectId = action.effectId;
|
|
1593
|
+
// P4 §1.1: invocation identity is derived, never minted — the chain's FIRST effect_id.
|
|
1594
|
+
// A provider_error commit armed `providerRetryPending`, so this effect CONTINUES the
|
|
1595
|
+
// pending invocation; otherwise it opens a new one. The chain itself lives in the
|
|
1596
|
+
// journal (each hop a Failed resolution input → new effect); this is the SessionLog
|
|
1597
|
+
// evidence projection of it.
|
|
1598
|
+
if (!this.providerRetryPending || this.activeProviderInvocationId === undefined) {
|
|
1599
|
+
this.activeProviderInvocationId = providerEffectId;
|
|
1600
|
+
}
|
|
1601
|
+
this.providerRetryPending = false;
|
|
1602
|
+
const invocationId = this.activeProviderInvocationId;
|
|
1603
|
+
// Host wall-clock, pure evidence (B7/DEC-2): never crosses into kernel input.
|
|
1604
|
+
const attemptStartedAtMs = Date.now();
|
|
1560
1605
|
const finalToolCalls = [];
|
|
1561
1606
|
let finalText = "";
|
|
1562
1607
|
// I5: governance schema-level pre-filter. When a declarative GovernancePolicy is loaded
|
|
@@ -1588,6 +1633,9 @@ export class RuntimeRunner {
|
|
|
1588
1633
|
let turnCacheTelemetrySource;
|
|
1589
1634
|
let turnCacheReadBySlot;
|
|
1590
1635
|
let turnStopReason;
|
|
1636
|
+
// P4 §2: the raw postflight provider usage frame, kept whole so the attempt's
|
|
1637
|
+
// measurement carries full fields (only the settlement crosses the kernel boundary, B4).
|
|
1638
|
+
let turnProviderUsage;
|
|
1591
1639
|
const providerPlan = createProviderRequestPlanForProvider(this.opts.provider, context, tools, ext);
|
|
1592
1640
|
const recorded = measurementForPlan(providerPlan, recordedMeasurements.get(providerPlan.fingerprint));
|
|
1593
1641
|
let promptMeasurement = recorded;
|
|
@@ -1614,6 +1662,7 @@ export class RuntimeRunner {
|
|
|
1614
1662
|
kind: "prompt_measured",
|
|
1615
1663
|
turn: runtime.turn(),
|
|
1616
1664
|
measurement: promptMeasurement,
|
|
1665
|
+
effect_id: providerEffectId,
|
|
1617
1666
|
});
|
|
1618
1667
|
}
|
|
1619
1668
|
const reservedPromptTokens = (this.opts.promptBudget?.promptOverheadTokens ?? 0)
|
|
@@ -1626,6 +1675,23 @@ export class RuntimeRunner {
|
|
|
1626
1675
|
&& promptMeasurement.source.kind !== "heuristic"
|
|
1627
1676
|
&& promptMeasurement.inputTokens + reservedPromptTokens > this.opts.maxTokens;
|
|
1628
1677
|
if (context.budgetOverflow || measuredOverflow) {
|
|
1678
|
+
// P4 §1.2: blocked BEFORE any transport — zero rungs, status rejected. The
|
|
1679
|
+
// fingerprint still binds the would-be request to its prompt_measured record (G2).
|
|
1680
|
+
await this.appendProviderAttempt(sessionId, {
|
|
1681
|
+
effectId: providerEffectId,
|
|
1682
|
+
attemptSeq: 1,
|
|
1683
|
+
route: this.providerRoute,
|
|
1684
|
+
requestFingerprint: providerPlan.fingerprint,
|
|
1685
|
+
status: "rejected",
|
|
1686
|
+
transportRungs: 0,
|
|
1687
|
+
lastErrorClass: "context_overflow",
|
|
1688
|
+
startedAtMs: attemptStartedAtMs,
|
|
1689
|
+
finishedAtMs: Date.now(),
|
|
1690
|
+
wireEvidence: {
|
|
1691
|
+
protocol: this.providerRoute.protocol,
|
|
1692
|
+
request_fingerprint: providerPlan.fingerprint,
|
|
1693
|
+
},
|
|
1694
|
+
});
|
|
1629
1695
|
action = await this.commitKernelAction(runtime, this.pendingObservations, {
|
|
1630
1696
|
kind: "provider_error",
|
|
1631
1697
|
effect_id: providerEffectId,
|
|
@@ -1633,6 +1699,7 @@ export class RuntimeRunner {
|
|
|
1633
1699
|
error_kind: "context_overflow",
|
|
1634
1700
|
retryable: false,
|
|
1635
1701
|
});
|
|
1702
|
+
this.providerRetryPending = action.kind === "call_provider";
|
|
1636
1703
|
continue;
|
|
1637
1704
|
}
|
|
1638
1705
|
const abortSignal = this.abortController?.signal;
|
|
@@ -1648,6 +1715,7 @@ export class RuntimeRunner {
|
|
|
1648
1715
|
turnTokens = usageEvt.totalTokens;
|
|
1649
1716
|
turnInputTokens = usageEvt.inputTokens ?? 0;
|
|
1650
1717
|
turnOutputTokens = usageEvt.outputTokens ?? 0;
|
|
1718
|
+
turnProviderUsage = usageEvt.providerUsage ?? turnProviderUsage;
|
|
1651
1719
|
// P0-C: capture the prompt-cache split for the tool-gating hit-rate baseline.
|
|
1652
1720
|
turnCacheReadTokens = usageEvt.cacheReadInputTokens ?? 0;
|
|
1653
1721
|
turnCacheCreationTokens = usageEvt.cacheCreationInputTokens ?? 0;
|
|
@@ -1679,6 +1747,7 @@ export class RuntimeRunner {
|
|
|
1679
1747
|
source: postflight.source,
|
|
1680
1748
|
confidence: postflight.confidence,
|
|
1681
1749
|
},
|
|
1750
|
+
effect_id: providerEffectId,
|
|
1682
1751
|
});
|
|
1683
1752
|
}
|
|
1684
1753
|
// Phase 4: stop_reason drives the kernel's max-output-tokens recovery. The closing
|
|
@@ -1706,6 +1775,26 @@ export class RuntimeRunner {
|
|
|
1706
1775
|
const provider = this.opts.provider.descriptor?.().provider ?? "unknown";
|
|
1707
1776
|
const providerError = classifyProviderError(provider, err);
|
|
1708
1777
|
const message = providerError.message;
|
|
1778
|
+
// P4 §1.2: the transport ladder is exhausted — one attempt record, rung count from
|
|
1779
|
+
// provider telemetry (1 on the single-shot stream path), error CLASS only (B1:
|
|
1780
|
+
// never the raw vendor text).
|
|
1781
|
+
const telemetry = this.opts.provider.peekTransportTelemetry?.();
|
|
1782
|
+
await this.appendProviderAttempt(sessionId, {
|
|
1783
|
+
effectId: providerEffectId,
|
|
1784
|
+
attemptSeq: 1,
|
|
1785
|
+
route: this.providerRoute,
|
|
1786
|
+
requestFingerprint: providerPlan.fingerprint,
|
|
1787
|
+
status: "transport_exhausted",
|
|
1788
|
+
transportRungs: telemetry?.rungs ?? 1,
|
|
1789
|
+
lastErrorClass: providerError.kind,
|
|
1790
|
+
startedAtMs: attemptStartedAtMs,
|
|
1791
|
+
finishedAtMs: Date.now(),
|
|
1792
|
+
wireEvidence: {
|
|
1793
|
+
protocol: this.providerRoute.protocol,
|
|
1794
|
+
request_fingerprint: providerPlan.fingerprint,
|
|
1795
|
+
...(telemetry?.responseId !== undefined ? { response_id: telemetry.responseId } : {}),
|
|
1796
|
+
},
|
|
1797
|
+
});
|
|
1709
1798
|
// Reactive recovery is now a kernel decision. Forward the raw provider error and
|
|
1710
1799
|
// dispatch whatever the kernel returns: `call_provider` to retry with a freshly
|
|
1711
1800
|
// compacted context, or `done` to terminate with an honest `ContextOverflow`. The
|
|
@@ -1719,6 +1808,9 @@ export class RuntimeRunner {
|
|
|
1719
1808
|
message,
|
|
1720
1809
|
...providerErrorEventFields(providerError),
|
|
1721
1810
|
});
|
|
1811
|
+
// P4 §1.1: a kernel-recovered retry CONTINUES this invocation (the journal holds the
|
|
1812
|
+
// causation hop); a terminal closes it.
|
|
1813
|
+
this.providerRetryPending = action.kind === "call_provider";
|
|
1722
1814
|
// Withholding (query.ts parity): surface the raw provider error only when the kernel
|
|
1723
1815
|
// could NOT recover (it returned a terminal). On a recovered retry (`call_provider`)
|
|
1724
1816
|
// the error stays hidden, so embedders that terminate on `error` events don't see a
|
|
@@ -1731,6 +1823,23 @@ export class RuntimeRunner {
|
|
|
1731
1823
|
}
|
|
1732
1824
|
// Do not commit partial provider output after host cancellation.
|
|
1733
1825
|
if (abortSignal?.aborted) {
|
|
1826
|
+
// P4 §1.2: host cancellation mid-stream — the attempt is evidence too.
|
|
1827
|
+
const telemetry = this.opts.provider.peekTransportTelemetry?.();
|
|
1828
|
+
await this.appendProviderAttempt(sessionId, {
|
|
1829
|
+
effectId: providerEffectId,
|
|
1830
|
+
attemptSeq: 1,
|
|
1831
|
+
route: this.providerRoute,
|
|
1832
|
+
requestFingerprint: providerPlan.fingerprint,
|
|
1833
|
+
status: "aborted",
|
|
1834
|
+
transportRungs: telemetry?.rungs ?? 1,
|
|
1835
|
+
startedAtMs: attemptStartedAtMs,
|
|
1836
|
+
finishedAtMs: Date.now(),
|
|
1837
|
+
wireEvidence: {
|
|
1838
|
+
protocol: this.providerRoute.protocol,
|
|
1839
|
+
request_fingerprint: providerPlan.fingerprint,
|
|
1840
|
+
...(telemetry?.responseId !== undefined ? { response_id: telemetry.responseId } : {}),
|
|
1841
|
+
},
|
|
1842
|
+
});
|
|
1734
1843
|
action = await this.commitKernelAction(runtime, this.pendingObservations, {
|
|
1735
1844
|
kind: "cancel_operation",
|
|
1736
1845
|
reason: this.cancellationReason ?? "user",
|
|
@@ -1762,12 +1871,37 @@ export class RuntimeRunner {
|
|
|
1762
1871
|
toolCalls: canonicalToolCalls,
|
|
1763
1872
|
tokenCount: turnOutputTokens || turnTokens || undefined,
|
|
1764
1873
|
};
|
|
1874
|
+
// P4 §2: assemble the measurement from the exact numbers that cross the boundary today
|
|
1875
|
+
// (inputTokens/outputTokens turn counters), enriched with the raw provider frame's cache
|
|
1876
|
+
// split and reasoning fields. An invalid frame degrades to no measurement (evidence
|
|
1877
|
+
// never breaks a run); the settlement then falls back to the raw counts below.
|
|
1878
|
+
const attemptUsage = (turnInputTokens > 0 || turnOutputTokens > 0)
|
|
1879
|
+
? tryNormalizeProviderUsage({
|
|
1880
|
+
inputTokens: turnInputTokens,
|
|
1881
|
+
outputTokens: turnOutputTokens,
|
|
1882
|
+
...(turnProviderUsage?.cacheReadInputTokens !== undefined
|
|
1883
|
+
? { cacheReadInputTokens: turnProviderUsage.cacheReadInputTokens }
|
|
1884
|
+
: turnCacheReadTokens > 0 ? { cacheReadInputTokens: turnCacheReadTokens } : {}),
|
|
1885
|
+
...(turnProviderUsage?.cacheCreationInputTokens !== undefined
|
|
1886
|
+
? { cacheCreationInputTokens: turnProviderUsage.cacheCreationInputTokens }
|
|
1887
|
+
: turnCacheCreationTokens > 0 ? { cacheCreationInputTokens: turnCacheCreationTokens } : {}),
|
|
1888
|
+
...(turnProviderUsage?.reasoningTokens !== undefined
|
|
1889
|
+
? { reasoningTokens: turnProviderUsage.reasoningTokens } : {}),
|
|
1890
|
+
cacheTelemetryStatus: turnCacheTelemetryStatus,
|
|
1891
|
+
...(turnCacheTelemetrySource !== undefined
|
|
1892
|
+
? { cacheTelemetrySource: turnCacheTelemetrySource } : {}),
|
|
1893
|
+
})
|
|
1894
|
+
: undefined;
|
|
1895
|
+
const settlement = attemptUsage ? this.usageAccountingPolicy.settle(attemptUsage) : undefined;
|
|
1765
1896
|
const providerEvent = {
|
|
1766
1897
|
kind: "provider_result",
|
|
1767
1898
|
effect_id: providerEffectId,
|
|
1768
1899
|
message: messageToKernelMessage(assistantMessage),
|
|
1769
|
-
|
|
1770
|
-
|
|
1900
|
+
// P4-S2: observed_* now comes from the pinned policy's settlement of the measurement.
|
|
1901
|
+
// Under the default full-footprint policy these are provably the numbers the runner
|
|
1902
|
+
// has always fed (inputTokens/outputTokens verbatim under the same >0 gates).
|
|
1903
|
+
...(turnInputTokens > 0 ? { observed_input_tokens: settlement?.observed_input_tokens ?? turnInputTokens } : {}),
|
|
1904
|
+
...(turnOutputTokens > 0 ? { observed_output_tokens: settlement?.observed_output_tokens ?? turnOutputTokens } : {}),
|
|
1771
1905
|
...(turnStopReason ? { stop_reason: turnStopReason } : {}),
|
|
1772
1906
|
};
|
|
1773
1907
|
if (this.opts.skillDir) {
|
|
@@ -1798,14 +1932,38 @@ export class RuntimeRunner {
|
|
|
1798
1932
|
}
|
|
1799
1933
|
}
|
|
1800
1934
|
}
|
|
1801
|
-
|
|
1935
|
+
// P4-S1: land the attempt evidence BEFORE the kernel resolution commits — the record
|
|
1936
|
+
// describes the transport fact, which exists regardless of what the kernel decides next.
|
|
1937
|
+
const attemptTelemetry = this.opts.provider.peekTransportTelemetry?.();
|
|
1802
1938
|
const providerReplay = peekProviderReplay(this.opts.provider, finalText, finalToolCalls);
|
|
1939
|
+
const wireEvidence = {
|
|
1940
|
+
protocol: this.providerRoute.protocol,
|
|
1941
|
+
request_fingerprint: providerPlan.fingerprint,
|
|
1942
|
+
...(attemptTelemetry?.responseId !== undefined ? { response_id: attemptTelemetry.responseId } : {}),
|
|
1943
|
+
...(providerReplay !== undefined ? { replay_state: providerReplay } : {}),
|
|
1944
|
+
};
|
|
1945
|
+
await this.appendProviderAttempt(sessionId, {
|
|
1946
|
+
effectId: providerEffectId,
|
|
1947
|
+
attemptSeq: 1,
|
|
1948
|
+
route: this.providerRoute,
|
|
1949
|
+
requestFingerprint: providerPlan.fingerprint,
|
|
1950
|
+
status: "success",
|
|
1951
|
+
transportRungs: attemptTelemetry?.rungs ?? 1,
|
|
1952
|
+
startedAtMs: attemptStartedAtMs,
|
|
1953
|
+
finishedAtMs: Date.now(),
|
|
1954
|
+
...(attemptUsage !== undefined ? { usage: attemptUsage } : {}),
|
|
1955
|
+
wireEvidence,
|
|
1956
|
+
});
|
|
1957
|
+
action = await this.commitKernelAction(runtime, this.pendingObservations, providerEvent);
|
|
1803
1958
|
await this.opts.sessionLog.append(sessionId, buildLlmCompletedEvent({
|
|
1804
1959
|
turn: runtime.turn(),
|
|
1805
1960
|
content: finalText,
|
|
1806
1961
|
tokenCount: turnOutputTokens || turnTokens || undefined,
|
|
1807
1962
|
toolCalls: finalToolCalls,
|
|
1808
1963
|
providerReplay,
|
|
1964
|
+
effectId: providerEffectId,
|
|
1965
|
+
invocationId,
|
|
1966
|
+
wireEvidence,
|
|
1809
1967
|
}));
|
|
1810
1968
|
// P0-C: emit per-turn tool-gating telemetry. `activeSkill` reflects the skill in effect
|
|
1811
1969
|
// GOING INTO this turn; a `skill` call here only takes effect next turn, so emit first, then
|
|
@@ -1840,7 +1998,7 @@ export class RuntimeRunner {
|
|
|
1840
1998
|
}
|
|
1841
1999
|
}
|
|
1842
2000
|
else if (action.kind === "request_approval") {
|
|
1843
|
-
const resolved = await this.resolveApprovalRequests(action.requests, runtime, sessionId);
|
|
2001
|
+
const resolved = await this.resolveApprovalRequests(action.requests, runtime, sessionId, action.effectId);
|
|
1844
2002
|
for (const event of resolved.events)
|
|
1845
2003
|
yield event;
|
|
1846
2004
|
action = await this.commitKernelAction(runtime, this.pendingObservations, {
|
|
@@ -2170,6 +2328,7 @@ export class RuntimeRunner {
|
|
|
2170
2328
|
token_count: r.tokenCount,
|
|
2171
2329
|
content: { blocks: toolOutputBlocksToDurable(r.contentParts?.length ? r.contentParts : [{ type: "text", text: r.output }]) },
|
|
2172
2330
|
})),
|
|
2331
|
+
effect_id: toolEffectId,
|
|
2173
2332
|
});
|
|
2174
2333
|
// The canonical provider resolution already activates a successfully resolved `skill` call.
|
|
2175
2334
|
// The host's remaining responsibility is to pin the resolved METHOD content — how to do
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { KernelPrimitive } from "./kernel-event-log.js";
|
|
2
|
-
import type { ContentPart, ProviderReplay, ToolCall, ToolErrorKind } from "../types.js";
|
|
3
|
-
import type { RecordedPromptMeasurement } from "../providers/request-plan.js";
|
|
2
|
+
import type { ContentPart, ProviderReplay, ProviderWireEvidence, ToolCall, ToolErrorKind } from "../types.js";
|
|
3
|
+
import type { RecordedPromptMeasurement, ResolvedProviderRoute } from "../providers/request-plan.js";
|
|
4
|
+
import type { ProviderAttemptRecord } from "./execution-evidence.js";
|
|
4
5
|
import type { MemoryRecall, MemoryScope } from "../memory/protocols.js";
|
|
5
6
|
import type { KernelJournal } from "./kernel-journal.js";
|
|
6
7
|
export type RollbackReason = {
|
|
@@ -30,6 +31,7 @@ export type SessionEvent = {
|
|
|
30
31
|
agent_id?: string;
|
|
31
32
|
system_prompt?: string;
|
|
32
33
|
attachments?: ContentPart[];
|
|
34
|
+
route?: ResolvedProviderRoute;
|
|
33
35
|
} | {
|
|
34
36
|
kind: "llm_completed";
|
|
35
37
|
turn: number;
|
|
@@ -37,11 +39,17 @@ export type SessionEvent = {
|
|
|
37
39
|
token_count?: number;
|
|
38
40
|
tool_calls: ToolCall[];
|
|
39
41
|
provider_replay?: ProviderReplay;
|
|
42
|
+
effect_id?: string;
|
|
43
|
+
invocation_id?: string;
|
|
44
|
+
wire_evidence?: ProviderWireEvidence;
|
|
40
45
|
} | {
|
|
41
46
|
kind: "prompt_measured";
|
|
42
47
|
turn: number;
|
|
43
48
|
measurement: RecordedPromptMeasurement;
|
|
44
|
-
|
|
49
|
+
effect_id?: string;
|
|
50
|
+
} | ({
|
|
51
|
+
kind: "provider_attempt";
|
|
52
|
+
} & ProviderAttemptRecord) | {
|
|
45
53
|
kind: "tool_requested";
|
|
46
54
|
turn: number;
|
|
47
55
|
calls: ToolCall[];
|
|
@@ -59,6 +67,7 @@ export type SessionEvent = {
|
|
|
59
67
|
blocks: Record<string, unknown>[];
|
|
60
68
|
};
|
|
61
69
|
}>;
|
|
70
|
+
effect_id?: string;
|
|
62
71
|
} | {
|
|
63
72
|
kind: "tool_argument_repaired";
|
|
64
73
|
turn: number;
|
|
@@ -326,6 +335,14 @@ export type SessionEvent = {
|
|
|
326
335
|
reason: string;
|
|
327
336
|
coerced_from?: string;
|
|
328
337
|
};
|
|
338
|
+
export type SessionEventKind = SessionEvent["kind"];
|
|
339
|
+
/**
|
|
340
|
+
* The registered session-event vocabulary (F9 / S3, P7-S4). This list is the single authority
|
|
341
|
+
* the cross-SDK manifest fixture pins: a kind added here without the same-commit update to
|
|
342
|
+
* `tests/fixtures/sdk-conformance/canonical/session-event-vocabulary.json` and the python/wasm
|
|
343
|
+
* vocabularies turns cross-SDK conformance red. Declared in `SessionEvent` union order.
|
|
344
|
+
*/
|
|
345
|
+
export declare const SESSION_EVENT_KINDS: readonly ["run_started", "llm_completed", "prompt_measured", "provider_attempt", "tool_requested", "tool_completed", "tool_argument_repaired", "tool_denied", "permission_requested", "permission_resolved", "compressed", "page_out", "semantic_archive_pending", "semantic_archive_completed", "semantic_archive_failed", "page_in", "rollbacked", "capability_changed", "context_renewed", "suspended", "resumed", "tool_gated", "signal_delivery_disposed", "budget_exceeded", "budget_usage_reported", "operation_cancelled", "milestone_advanced", "milestone_blocked", "checkpoint_taken", "entropy_sample", "entropy_alert", "agent_process_changed", "memory_written", "memory_queried", "memory_validation_failed", "memory_write_failed", "memory_query_failed", "memory_retrieval_result", "workflow_node_completed", "workflow_nodes_submitted", "workflow_batch_spawned", "workflow_completed", "kernel_observation", "run_terminal", "summary_upgraded", "group_member_joined", "group_budget_charged", "round_started", "round_paced"];
|
|
329
346
|
/**
|
|
330
347
|
* The business-projection log (spec §9.2): run started/terminal, stream events, observations,
|
|
331
348
|
* provider/tool presentation, audit metadata.
|