@h1v35/hivex 0.2.0 → 0.2.2

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 (39) hide show
  1. package/README.md +55 -163
  2. package/docs/CONTEXT.md +20 -36
  3. package/docs/README.md +6 -12
  4. package/docs/adr/0003-independent-bun-installation.md +5 -19
  5. package/docs/adr/0010-practical-knowledge-assistance.md +28 -81
  6. package/docs/adr/0011-shared-knowledge-and-selective-history.md +16 -43
  7. package/docs/guidelines/engineering.md +74 -0
  8. package/docs/procedures/self-hosted-runner.md +7 -0
  9. package/package.json +32 -11
  10. package/skills/hivex/SKILL.md +28 -92
  11. package/skills/hivex/references/markdown.md +12 -42
  12. package/src/cli/diagnostic.ts +21 -11
  13. package/src/cli.ts +46 -36
  14. package/src/documents.ts +502 -320
  15. package/src/errors.ts +8 -6
  16. package/src/implementation.ts +185 -87
  17. package/src/ingestion-units.ts +107 -64
  18. package/src/knowledge-maintenance.ts +35 -22
  19. package/src/knowledge-model.ts +386 -268
  20. package/src/knowledge-serialization.ts +239 -0
  21. package/src/knowledge-snapshot.ts +100 -77
  22. package/src/knowledge-store.ts +634 -453
  23. package/src/knowledge.ts +1001 -758
  24. package/src/markdown.ts +107 -45
  25. package/src/model/connection.ts +134 -76
  26. package/src/model/failure.ts +46 -23
  27. package/src/model/invoke.ts +346 -166
  28. package/src/model/profile.ts +201 -103
  29. package/src/model/rpc-error.ts +21 -0
  30. package/src/model/server.ts +151 -82
  31. package/src/model/thread.ts +24 -14
  32. package/src/model/transcript.ts +87 -46
  33. package/src/ordering.ts +9 -0
  34. package/src/retrieval/lexical.ts +64 -41
  35. package/src/review.ts +83 -55
  36. package/src/runtime.d.ts +4 -0
  37. package/src/snapshot-command.ts +82 -43
  38. package/src/source-relocation.ts +222 -0
  39. package/docs/engineering.md +0 -174
@@ -1,23 +1,25 @@
1
1
  import { mkdtempSync, readdirSync, realpathSync, rmSync } from 'node:fs';
2
2
  import { tmpdir } from 'node:os';
3
- import { join } from 'node:path';
3
+ import path from 'node:path';
4
4
  import { z } from 'zod';
5
5
  import { startServer } from './server.ts';
6
- import { knowledgeTurn, type ProfileEvidence } from './profile.ts';
7
- import { captureTranscript, type Usage } from './transcript.ts';
6
+ import { knowledgeTurn } from './profile.ts';
8
7
  import { startKnowledgeThread } from './thread.ts';
9
8
  import { failureDiagnostic, ServerAdmissionFailure } from './failure.ts';
9
+ import { captureTranscript } from './transcript.ts';
10
+ import type { ProfileEvidence } from './profile.ts';
11
+ import type { Usage } from './transcript.ts';
10
12
 
11
13
  export type NativeProcessStarted = (nativeProcessId: number) => void;
12
14
 
13
- export type InvocationOptions = {
15
+ export interface InvocationOptions {
14
16
  binary: string;
15
17
  prompt: string;
16
18
  schema: Record<string, unknown>;
17
19
  deadlineMilliseconds: number;
18
20
  onNativeProcessStarted?: NativeProcessStarted;
19
- };
20
- export type InvocationReport = {
21
+ }
22
+ export interface InvocationReport {
21
23
  outcome: string;
22
24
  code?: string;
23
25
  deadlineMilliseconds: number;
@@ -32,22 +34,35 @@ export type InvocationReport = {
32
34
  admission?: ProfileEvidence & { launchPolicyHash: string };
33
35
  diagnostic?: Record<string, unknown>;
34
36
  nativeProcessId?: number;
35
- };
37
+ }
36
38
 
37
- class ModelTimeout extends Error {}
38
- class ModelCancelled extends Error {}
39
+ class ModelAbortError extends Error {
40
+ name = 'ModelAbortError';
41
+ readonly kind: 'cancelled' | 'timeout';
42
+
43
+ constructor(kind: 'cancelled' | 'timeout', options?: ErrorOptions) {
44
+ super('', options);
45
+ this.kind = kind;
46
+ }
47
+ }
39
48
 
40
- async function completedWithin(options: {
49
+ const completedWithin = async (options: {
41
50
  captured: ReturnType<typeof captureTranscript>;
42
51
  server: Awaited<ReturnType<typeof startServer>>;
43
52
  milliseconds: number;
44
53
  signal?: AbortSignal;
45
- }) {
54
+ }) => {
46
55
  const expired = Promise.withResolvers<never>();
47
- const cancelled = () => expired.reject(new ModelCancelled());
56
+ const cancelled = (): void => {
57
+ expired.reject(new ModelAbortError('cancelled'));
58
+ };
48
59
  options.signal?.addEventListener('abort', cancelled, { once: true });
49
- if (options.signal?.aborted) cancelled();
50
- const timer = setTimeout(() => expired.reject(new ModelTimeout()), options.milliseconds);
60
+ if (options.signal?.aborted === true) {
61
+ cancelled();
62
+ }
63
+ const timer = setTimeout(() => {
64
+ expired.reject(new ModelAbortError('timeout'));
65
+ }, options.milliseconds);
51
66
  try {
52
67
  return await Promise.race([
53
68
  options.captured.done.promise,
@@ -58,208 +73,373 @@ async function completedWithin(options: {
58
73
  clearTimeout(timer);
59
74
  options.signal?.removeEventListener('abort', cancelled);
60
75
  }
61
- }
76
+ };
62
77
 
63
- async function interrupt(options: {
64
- captured: ReturnType<typeof captureTranscript>;
78
+ const isInterruptedTurn = function isInterruptedTurn(
79
+ end: Awaited<ReturnType<typeof completedWithin>>,
80
+ threadId: string,
81
+ turnId: string
82
+ ) {
83
+ return end.threadId === threadId && end.turn.id === turnId && end.turn.status === 'interrupted';
84
+ };
85
+
86
+ const isInterruptRequestAccepted = async (options: {
65
87
  server: Awaited<ReturnType<typeof startServer>>;
66
88
  threadId: string;
67
89
  turnId: string;
68
- }) {
90
+ }) => {
69
91
  try {
70
92
  await options.server.rpc.request(
71
93
  'turn/interrupt',
72
94
  { threadId: options.threadId, turnId: options.turnId },
73
- { timeoutMilliseconds: 5000 },
95
+ { timeoutMilliseconds: 5000 }
74
96
  );
97
+ return true;
98
+ } catch {
99
+ return false;
100
+ }
101
+ };
102
+
103
+ const isInterrupted = async (options: {
104
+ captured: ReturnType<typeof captureTranscript>;
105
+ server: Awaited<ReturnType<typeof startServer>>;
106
+ threadId: string;
107
+ turnId: string;
108
+ }) => {
109
+ const isInterruptAccepted = await isInterruptRequestAccepted(options);
110
+ if (!isInterruptAccepted) {
111
+ return false;
112
+ }
113
+ try {
75
114
  const end = await completedWithin({
76
115
  captured: options.captured,
77
- server: options.server,
78
116
  milliseconds: 5000,
117
+ server: options.server,
79
118
  });
80
- return (
81
- end.threadId === options.threadId &&
82
- end.turn.id === options.turnId &&
83
- end.turn.status === 'interrupted'
84
- );
119
+ return isInterruptedTurn(end, options.threadId, options.turnId);
85
120
  } catch {
86
121
  return false;
87
122
  }
123
+ };
124
+
125
+ const turnStartResponse = z.looseObject({
126
+ turn: z.looseObject({ id: z.string() }),
127
+ });
128
+
129
+ interface RunTurnOptions extends InvocationOptions {
130
+ captured: ReturnType<typeof captureTranscript>;
131
+ server: Awaited<ReturnType<typeof startServer>>;
132
+ signal: AbortSignal;
133
+ threadId: string;
134
+ workspace: string;
88
135
  }
89
136
 
90
- async function runTurn(
91
- options: InvocationOptions & {
92
- server: Awaited<ReturnType<typeof startServer>>;
93
- captured: ReturnType<typeof captureTranscript>;
94
- workspace: string;
95
- threadId: string;
96
- signal: AbortSignal;
97
- },
98
- ) {
137
+ interface InvocationResult {
138
+ value: unknown;
139
+ report: InvocationReport;
140
+ retry: boolean;
141
+ }
142
+
143
+ const createInvocationResult = (
144
+ value: unknown,
145
+ report: InvocationReport,
146
+ shouldRetry: boolean
147
+ ): InvocationResult => {
148
+ const valueField = { value };
149
+ const reportField = { report };
150
+ const retryField = { retry: shouldRetry };
151
+ return { ...valueField, ...reportField, ...retryField };
152
+ };
153
+
154
+ const failureCode = (options: { isCancelled: boolean; isTimeout: boolean }) => {
155
+ if (options.isCancelled) {
156
+ return 'MODEL_CANCELLED';
157
+ }
158
+ return options.isTimeout ? 'MODEL_TIMEOUT' : 'MODEL_PROTOCOL_FAILED';
159
+ };
160
+
161
+ const completeTurn = async (options: RunTurnOptions & { begin: number; turnId: string }) => {
162
+ if (options.signal.aborted) {
163
+ throw new ModelAbortError('cancelled');
164
+ }
165
+ const remaining = options.deadlineMilliseconds - (performance.now() - options.begin);
166
+ if (remaining <= 0) {
167
+ throw new ModelAbortError('timeout');
168
+ }
169
+ const end = await completedWithin({
170
+ captured: options.captured,
171
+ milliseconds: remaining,
172
+ server: options.server,
173
+ signal: options.signal,
174
+ });
175
+ if (
176
+ end.threadId !== options.threadId ||
177
+ end.turn.id !== options.turnId ||
178
+ end.turn.status !== 'completed'
179
+ ) {
180
+ throw new Error('Model completion was not established');
181
+ }
182
+ options.captured.assertValid({
183
+ threadId: options.threadId,
184
+ turnId: options.turnId,
185
+ });
186
+ const final = options.captured.items.at(-1);
187
+ const text = final?.item.text;
188
+ if (
189
+ text === undefined ||
190
+ text === '' ||
191
+ final?.threadId !== options.threadId ||
192
+ final.turnId !== options.turnId
193
+ ) {
194
+ throw new Error('Structured model output is missing');
195
+ }
196
+ if (readdirSync(options.workspace).length !== 0) {
197
+ throw new Error('Knowledge workspace was mutated');
198
+ }
199
+ return text;
200
+ };
201
+
202
+ const runTurn = async (options: RunTurnOptions) => {
99
203
  const { server, captured, threadId } = options;
100
204
  const begin = performance.now();
101
- const accepted = await server.rpc
102
- .request(
103
- 'turn/start',
104
- {
105
- threadId,
106
- ...knowledgeTurn,
107
- input: [{ type: 'text', text: options.prompt }],
108
- outputSchema: options.schema,
109
- },
110
- { timeoutMilliseconds: Math.min(options.deadlineMilliseconds, 30_000) },
111
- )
112
- .then((response) => z.looseObject({ turn: z.looseObject({ id: z.string() }) }).parse(response))
113
- .catch(() => null);
114
- if (!accepted) {
115
- const report: InvocationReport = {
116
- outcome: 'failed',
117
- code: 'MODEL_START_UNCONFIRMED',
118
- turnAccepted: 'unknown',
119
- threadId,
205
+ const inputTextType = { type: 'text' };
206
+ const inputText = { text: options.prompt };
207
+ const turnInput = {
208
+ ...inputTextType,
209
+ ...inputText,
210
+ };
211
+ const turnThread = { threadId };
212
+ const turnInputParameter = { input: [turnInput] };
213
+ const turnOutputSchema = { outputSchema: options.schema };
214
+ const turnParameters = {
215
+ ...turnThread,
216
+ ...knowledgeTurn,
217
+ ...turnInputParameter,
218
+ ...turnOutputSchema,
219
+ };
220
+ let accepted: z.infer<typeof turnStartResponse> | null;
221
+ try {
222
+ const response = await server.rpc.request('turn/start', turnParameters, {
223
+ timeoutMilliseconds: Math.min(options.deadlineMilliseconds, 30_000),
224
+ });
225
+ accepted = turnStartResponse.parse(response);
226
+ } catch {
227
+ accepted = null;
228
+ }
229
+ if (accepted === null) {
230
+ const reportOutcome = { outcome: 'failed' };
231
+ const reportCode = { code: 'MODEL_START_UNCONFIRMED' };
232
+ const reportTurnAccepted = { turnAccepted: 'unknown' as const };
233
+ const reportThreadId = { threadId };
234
+ const reportDeadlineMilliseconds = {
120
235
  deadlineMilliseconds: options.deadlineMilliseconds,
121
- usage: null,
122
236
  };
123
- return { value: null, report, retry: false };
237
+ const reportUsage = { usage: null };
238
+ const report: InvocationReport = {
239
+ ...reportOutcome,
240
+ ...reportCode,
241
+ ...reportTurnAccepted,
242
+ ...reportThreadId,
243
+ ...reportDeadlineMilliseconds,
244
+ ...reportUsage,
245
+ };
246
+ return createInvocationResult(null, report, false);
124
247
  }
125
248
  const turnId = accepted.turn.id;
126
249
  try {
127
- if (options.signal.aborted) throw new ModelCancelled();
128
- const remaining = options.deadlineMilliseconds - (performance.now() - begin);
129
- if (remaining <= 0) throw new ModelTimeout();
130
- const end = await completedWithin({ ...options, milliseconds: remaining });
131
- if (end.threadId !== threadId || end.turn.id !== turnId || end.turn.status !== 'completed')
132
- throw new Error('Model completion was not established');
133
- captured.assertValid({ threadId, turnId });
134
- const final = captured.items.at(-1);
135
- if (!final || final.threadId !== threadId || final.turnId !== turnId || !final.item.text)
136
- throw new Error('Structured model output is missing');
137
- if (readdirSync(options.workspace).length) throw new Error('Knowledge workspace was mutated');
138
- const report: InvocationReport = {
139
- outcome: 'completed',
140
- threadId,
141
- turnId,
142
- turnAccepted: 'confirmed',
250
+ const value = await completeTurn({ ...options, begin, turnId });
251
+ const reportOutcome = { outcome: 'completed' };
252
+ const reportThreadId = { threadId };
253
+ const reportTurnId = { turnId };
254
+ const reportTurnAccepted = { turnAccepted: 'confirmed' as const };
255
+ const reportDeadlineMilliseconds = {
143
256
  deadlineMilliseconds: options.deadlineMilliseconds,
144
- usage: captured.measured({ threadId, turnId }),
145
257
  };
146
- return { value: final.item.text, report, retry: false };
147
- } catch (error) {
148
- const confirmed = await interrupt({ ...options, turnId });
149
- const timeout = error instanceof ModelTimeout;
150
- const cancelled = error instanceof ModelCancelled;
258
+ const reportUsage = { usage: captured.measured({ threadId, turnId }) };
151
259
  const report: InvocationReport = {
152
- outcome: timeout ? 'timeout' : 'failed',
153
- threadId,
260
+ ...reportOutcome,
261
+ ...reportThreadId,
262
+ ...reportTurnId,
263
+ ...reportTurnAccepted,
264
+ ...reportDeadlineMilliseconds,
265
+ ...reportUsage,
266
+ };
267
+ return createInvocationResult(value, report, false);
268
+ } catch (error) {
269
+ const isInterruptionConfirmed = await isInterrupted({
270
+ ...options,
154
271
  turnId,
155
- code: failureCode({ timeout, cancelled }),
156
- interruption: confirmed ? 'confirmed' : 'unconfirmed',
157
- turnAccepted: 'confirmed',
272
+ });
273
+ const isTimeout = error instanceof ModelAbortError && error.kind === 'timeout';
274
+ const isCancelled = error instanceof ModelAbortError && error.kind === 'cancelled';
275
+ const reportOutcome = {
276
+ outcome: isTimeout ? 'timeout' : 'failed',
277
+ };
278
+ const reportThreadId = { threadId };
279
+ const reportTurnId = { turnId };
280
+ const reportCode = { code: failureCode({ isCancelled, isTimeout }) };
281
+ const reportInterruption = {
282
+ interruption: isInterruptionConfirmed ? 'confirmed' : 'unconfirmed',
283
+ };
284
+ const reportTurnAccepted = { turnAccepted: 'confirmed' as const };
285
+ const reportDeadlineMilliseconds = {
158
286
  deadlineMilliseconds: options.deadlineMilliseconds,
159
- usage: captured.measured({ threadId, turnId }),
160
287
  };
161
- return { value: null, report, retry: timeout && confirmed };
288
+ const reportUsage = { usage: captured.measured({ threadId, turnId }) };
289
+ const report: InvocationReport = {
290
+ ...reportOutcome,
291
+ ...reportThreadId,
292
+ ...reportTurnId,
293
+ ...reportCode,
294
+ ...reportInterruption,
295
+ ...reportTurnAccepted,
296
+ ...reportDeadlineMilliseconds,
297
+ ...reportUsage,
298
+ };
299
+ return createInvocationResult(null, report, isTimeout && isInterruptionConfirmed);
162
300
  }
301
+ };
302
+
303
+ const captureFailure = async <Value>(promise: Promise<Value>) => {
304
+ try {
305
+ return { value: await promise };
306
+ } catch (error) {
307
+ return { error };
308
+ }
309
+ };
310
+
311
+ interface InvocationResource {
312
+ server?: Awaited<ReturnType<typeof startServer>>;
313
+ result: InvocationResult;
163
314
  }
164
315
 
165
- export async function invokeModel(options: InvocationOptions) {
166
- const startedAt = new Date().toISOString();
316
+ export const invokeModel = async (options: InvocationOptions) => {
317
+ const currentTime = new Date();
318
+ const startedAt = currentTime.toISOString();
167
319
  const began = performance.now();
168
- const workspace = realpathSync(mkdtempSync(join(tmpdir(), 'hivex-model-')));
320
+ const workspace = realpathSync(mkdtempSync(path.join(tmpdir(), 'hivex-model-')));
169
321
  const captured = captureTranscript();
170
322
  const controller = new AbortController();
171
- const cancel = () => controller.abort();
323
+ const cancel = (): void => {
324
+ controller.abort();
325
+ };
172
326
  process.on('SIGINT', cancel);
173
327
  process.on('SIGTERM', cancel);
174
- const initialReport: InvocationReport = {
175
- outcome: 'failed',
176
- code: 'MODEL_ADMISSION_FAILED',
328
+ const initialReportOutcome = { outcome: 'failed' };
329
+ const initialReportCode = { code: 'MODEL_ADMISSION_FAILED' };
330
+ const initialReportDeadlineMilliseconds = {
177
331
  deadlineMilliseconds: options.deadlineMilliseconds,
178
- usage: null,
179
332
  };
180
- const resource: {
181
- server?: Awaited<ReturnType<typeof startServer>>;
182
- result: { value: unknown; report: InvocationReport; retry: boolean };
183
- } = { result: { value: null, report: initialReport, retry: false } };
184
- try {
185
- resource.server = await startServer({
186
- binary: options.binary,
187
- workspace,
188
- signal: controller.signal,
189
- notification: captured.notification,
190
- interaction: () => {
191
- throw new Error('Knowledge execution cannot request interaction');
192
- },
193
- });
194
- options.onNativeProcessStarted?.(resource.server.pid);
195
- const threadId = await startKnowledgeThread({
196
- rpc: resource.server.rpc,
197
- workspace,
198
- signal: controller.signal,
199
- });
200
- controller.signal.throwIfAborted();
201
- resource.result = await runTurn({
202
- ...options,
203
- captured,
204
- workspace,
205
- server: resource.server,
206
- threadId,
207
- signal: controller.signal,
208
- });
209
- } catch (error) {
210
- if (controller.signal.aborted) initialReport.code = 'MODEL_CANCELLED';
333
+ const initialReportUsage = { usage: null };
334
+ const initialReport: InvocationReport = {
335
+ ...initialReportOutcome,
336
+ ...initialReportCode,
337
+ ...initialReportDeadlineMilliseconds,
338
+ ...initialReportUsage,
339
+ };
340
+ const resource: InvocationResource = {
341
+ result: createInvocationResult(null, initialReport, false),
342
+ };
343
+ const execution = await captureFailure(
344
+ (async () => {
345
+ const server = await startServer({
346
+ binary: options.binary,
347
+ interaction: () => {
348
+ throw new Error('Knowledge execution cannot request interaction');
349
+ },
350
+ notification: captured.notification,
351
+ signal: controller.signal,
352
+ workspace,
353
+ });
354
+ resource.server = server;
355
+ if (options.onNativeProcessStarted !== undefined) {
356
+ options.onNativeProcessStarted(server.pid);
357
+ }
358
+ const threadId = await startKnowledgeThread({
359
+ rpc: server.rpc,
360
+ signal: controller.signal,
361
+ workspace,
362
+ });
363
+ controller.signal.throwIfAborted();
364
+ resource.result = await runTurn({
365
+ ...options,
366
+ captured,
367
+ server,
368
+ signal: controller.signal,
369
+ threadId,
370
+ workspace,
371
+ });
372
+ })()
373
+ );
374
+ if ('error' in execution) {
375
+ const { error } = execution;
376
+ if (controller.signal.aborted) {
377
+ initialReport.code = 'MODEL_CANCELLED';
378
+ }
211
379
  initialReport.diagnostic = failureDiagnostic(error);
212
380
  if (error instanceof ServerAdmissionFailure) {
213
381
  initialReport.cleanup = error.cleanup;
214
382
  initialReport.nativeProcessId = error.processId;
215
383
  initialReport.admission = error.admission;
216
384
  }
217
- resource.result = { value: null, report: initialReport, retry: false };
218
- } finally {
219
- try {
385
+ resource.result = createInvocationResult(null, initialReport, false);
386
+ }
387
+ const cleanup = await captureFailure(
388
+ (async () => {
220
389
  await resource.server?.stop();
221
- rmSync(workspace, { recursive: true, force: true });
222
- resource.result.report.cleanup = resource.server
223
- ? 'confirmed'
224
- : (resource.result.report.cleanup ?? 'not-observed');
225
- } catch {
226
- resource.result = {
227
- value: null,
228
- retry: false,
229
- report: {
230
- ...resource.result.report,
231
- outcome: 'failed',
232
- code: 'MODEL_CLEANUP_FAILED',
233
- cleanup: 'failed',
234
- },
235
- };
236
- }
237
- process.off('SIGINT', cancel);
238
- process.off('SIGTERM', cancel);
390
+ rmSync(workspace, { force: true, recursive: true });
391
+ resource.result.report.cleanup =
392
+ resource.server === undefined
393
+ ? (resource.result.report.cleanup ?? 'not-observed')
394
+ : 'confirmed';
395
+ })()
396
+ );
397
+ if ('error' in cleanup) {
398
+ const cleanupReportOutcome = { outcome: 'failed' };
399
+ const cleanupReportCode = { code: 'MODEL_CLEANUP_FAILED' };
400
+ const cleanupReportCleanup = { cleanup: 'failed' as const };
401
+ const cleanupReport = {
402
+ ...resource.result.report,
403
+ ...cleanupReportOutcome,
404
+ ...cleanupReportCode,
405
+ ...cleanupReportCleanup,
406
+ };
407
+ resource.result = createInvocationResult(null, cleanupReport, false);
408
+ }
409
+ process.off('SIGINT', cancel);
410
+ process.off('SIGTERM', cancel);
411
+ const { report } = resource.result;
412
+ const { threadId, turnId } = report;
413
+ if (threadId !== undefined && threadId !== '' && turnId !== undefined && turnId !== '') {
414
+ report.usage = captured.measured({ threadId, turnId });
239
415
  }
240
- const report = resource.result.report;
241
- if (report.threadId && report.turnId)
242
- report.usage = captured.measured({ threadId: report.threadId, turnId: report.turnId });
243
416
  if (captured.invalid && report.outcome === 'completed') {
244
- resource.result = {
245
- value: null,
246
- retry: false,
247
- report: { ...report, outcome: 'failed', code: 'MODEL_PROTOCOL_FAILED' },
417
+ const protocolReportOutcome = { outcome: 'failed' };
418
+ const protocolReportCode = { code: 'MODEL_PROTOCOL_FAILED' };
419
+ const protocolReport = {
420
+ ...report,
421
+ ...protocolReportOutcome,
422
+ ...protocolReportCode,
248
423
  };
424
+ resource.result = createInvocationResult(null, protocolReport, false);
249
425
  }
250
- return {
251
- ...resource.result,
252
- report: {
253
- ...resource.result.report,
254
- admission: resource.server?.admission ?? resource.result.report.admission,
255
- nativeProcessId: resource.server?.pid ?? resource.result.report.nativeProcessId,
256
- startedAt,
257
- durationMilliseconds: Math.round(performance.now() - began),
258
- },
426
+ const finalReport = resource.result.report;
427
+ const finalAdmission = {
428
+ admission: resource.server?.admission ?? finalReport.admission,
259
429
  };
260
- }
261
-
262
- function failureCode(options: { timeout: boolean; cancelled: boolean }) {
263
- if (options.cancelled) return 'MODEL_CANCELLED';
264
- return options.timeout ? 'MODEL_TIMEOUT' : 'MODEL_PROTOCOL_FAILED';
265
- }
430
+ const finalNativeProcessId = {
431
+ nativeProcessId: resource.server?.pid ?? finalReport.nativeProcessId,
432
+ };
433
+ const finalStartedAt = { startedAt };
434
+ const finalDurationMilliseconds = {
435
+ durationMilliseconds: Math.round(performance.now() - began),
436
+ };
437
+ const reportWithMetadata = {
438
+ ...finalReport,
439
+ ...finalAdmission,
440
+ ...finalNativeProcessId,
441
+ ...finalStartedAt,
442
+ ...finalDurationMilliseconds,
443
+ };
444
+ return { ...resource.result, report: reportWithMetadata };
445
+ };