@akagilnc/pi-workflow-roles 0.1.5204 → 0.1.5212

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.
@@ -312,26 +312,14 @@ export async function readLatestSubmissionOutcome(cwd, runId, homeOrScope) {
312
312
  }
313
313
  async function restoreState(cwd, runId, scope) {
314
314
  const located = await readOwnedSubmissionRecords(cwd, runId, scope);
315
- // Unknown-run empty set: no prior chain. Owned rows without a file are an internal bug.
316
315
  if (located.file === undefined) {
317
316
  if (located.owned.length !== 0) {
318
317
  throw new Error(`submission ledger invariant: owned rows present without recordFile for run ${runId}`);
319
318
  }
320
319
  return { sequence: 0 };
321
320
  }
322
- const { file, owned } = located;
323
- const last = owned.at(-1);
321
+ const { owned } = located;
324
322
  return {
325
- ...(last === undefined
326
- ? {}
327
- : {
328
- prior: {
329
- identity: last.identity,
330
- recordFile: file,
331
- kind: last.kind,
332
- level: last.level,
333
- },
334
- }),
335
323
  sequence: owned.reduce((maximum, record) => {
336
324
  const payload = record.payload;
337
325
  return payload?.type === "candidate" && typeof payload.sequence === "number"
@@ -362,7 +350,7 @@ function homeFromHostContext(context, home) {
362
350
  }
363
351
  /**
364
352
  * #959: seal one accepted submission without a model tool call.
365
- * Same ledger row shape and priorEventId chain as the terminating-tool wrap.
353
+ * Same ledger row shape as the terminating-tool wrap.
366
354
  * Used when a prose-exit seat (navigator) harvests the final assistant text.
367
355
  */
368
356
  export async function sealAcceptedSubmission(options) {
@@ -370,15 +358,10 @@ export async function sealAcceptedSubmission(options) {
370
358
  const attemptId = attemptIdentity(options.context, runId);
371
359
  const sessionParent = sessionParentFromHostContext(options.context);
372
360
  const home = homeFromHostContext(options.context, options.home);
373
- const state = await restoreState(options.context.cwd, runId, {
374
- ...(home === undefined ? {} : { home }),
375
- ...(sessionParent === undefined ? {} : { sessionParent }),
376
- });
377
- const pointer = sitianReport({
361
+ sitianReport({
378
362
  level: "event",
379
363
  kind: "sealed",
380
364
  subject: { runId, attemptId },
381
- ...(state.prior === undefined ? {} : { priorEventId: state.prior.identity }),
382
365
  payload: {
383
366
  type: "sealed",
384
367
  attemptId,
@@ -391,7 +374,6 @@ export async function sealAcceptedSubmission(options) {
391
374
  ...(home !== undefined ? { home } : {}),
392
375
  ...(sessionParent === undefined ? {} : { sessionParent }),
393
376
  });
394
- state.prior = pointer;
395
377
  }
396
378
  /**
397
379
  * Submission ledger host — record only (#836).
@@ -412,31 +394,28 @@ export function createSubmissionLedgerHost(host, outputTools, failInfrastructure
412
394
  states.set(runId, pending);
413
395
  return pending;
414
396
  })();
415
- const appendFor = (state, context, runId, attemptId, event) => {
397
+ const appendFor = (context, runId, attemptId, event) => {
416
398
  const home = resolveHomeFromContext(context);
417
399
  const sessionParent = sessionParentFromHostContext(context);
418
- const pointer = sitianReport({
400
+ return sitianReport({
419
401
  level: "event",
420
402
  kind: event.type,
421
403
  subject: { runId, attemptId },
422
- ...(state.prior === undefined ? {} : { priorEventId: state.prior.identity }),
423
404
  payload: event,
424
405
  source: "role-runtime",
425
406
  cwd: context.cwd,
426
407
  ...(home !== undefined ? { home } : {}),
427
408
  ...(sessionParent === undefined ? {} : { sessionParent }),
428
409
  });
429
- state.prior = pointer;
430
- return pointer;
431
410
  };
432
411
  host.on("turn_end", async (event, context) => {
433
412
  try {
434
413
  const runId = runIdentity(context);
435
414
  const attemptId = attemptIdentity(context, runId);
436
- const state = await stateFor(context, runId);
437
415
  const calls = event.calls.map(({ toolCallId: id, toolName: name }) => ({ id, name }));
438
416
  if (calls.length > 0) {
439
- appendFor(state, context, runId, attemptId, { type: "roundContext", attemptId, calls });
417
+ await stateFor(context, runId);
418
+ appendFor(context, runId, attemptId, { type: "roundContext", attemptId, calls });
440
419
  }
441
420
  }
442
421
  catch (error) {
@@ -465,7 +444,7 @@ export function createSubmissionLedgerHost(host, outputTools, failInfrastructure
465
444
  const runId = runIdentity(context);
466
445
  const attemptId = attemptIdentity(context, runId);
467
446
  const state = await stateFor(context, runId);
468
- const append = (event) => appendFor(state, context, runId, attemptId, event);
447
+ const append = (event) => appendFor(context, runId, attemptId, event);
469
448
  // #541 / #575: shared infra-declaration fail lives on the ledger seam.
470
449
  // #641 chain②: seats may bounce a misdeclared infrastructure failure
471
450
  // as correctable (2.1/2.2/2.3 keep paths).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.5204",
3
+ "version": "0.1.5212",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -29,7 +29,6 @@
29
29
  "!dist/package-resources/method-skill.js",
30
30
  "!dist/package-resources/method-skill-binding.js",
31
31
  "extensions",
32
- "scripts/generate-tool-execution-observation-schema.ts",
33
32
  "scripts/build-package.mjs",
34
33
  "src",
35
34
  "souls",
@@ -43,7 +42,7 @@
43
42
  "CLAUDE.md"
44
43
  ],
45
44
  "scripts": {
46
- "build": "tsx scripts/generate-tool-execution-observation-schema.ts && tsc -p tsconfig.build.json && node scripts/build-package.mjs",
45
+ "build": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && tsc -p tsconfig.build.json && node scripts/build-package.mjs",
47
46
  "prepack": "npm run build",
48
47
  "test": "node --import tsx --import ./scripts/test-process-env-preload.mjs --test test/unit/**/*.test.ts test/contract/**/*.test.ts",
49
48
  "test:fast": "node --import tsx --import ./scripts/test-process-env-preload.mjs --test-timeout=300000 --test test/unit/**/*.test.ts test/contract/**/*.test.ts",
@@ -1,4 +1,4 @@
1
- import { chmod, copyFile, mkdir, readFile, rm, writeFile } from "node:fs/promises";
1
+ import { chmod, copyFile, mkdir, readFile, writeFile } from "node:fs/promises";
2
2
  import { dirname, join, resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { build } from "esbuild";
@@ -20,7 +20,6 @@ const entries = [
20
20
  // Static import of navigator-work-base.
21
21
  "atomic-write",
22
22
  "public-role-summons",
23
- "pi/in-process-session",
24
23
  "activation-ledger-git",
25
24
  "activation-ledger-topology",
26
25
  "archivist-record-entry",
@@ -70,7 +69,6 @@ const entries = [
70
69
  "sitian-contracts",
71
70
  "sitian-facade",
72
71
  "sitian-reader",
73
- "stream-idle-guard",
74
72
  "typed-provider-http",
75
73
  "upstream-error-testimony",
76
74
  ];
@@ -17,7 +17,7 @@ finding 提**类别**;实例只作证据。一次找齐全,不逐轮抽样
17
17
 
18
18
  御批门槛:重大决策、设计、改变实际行为的机制与约束须合法。实现细节(字段名、内部形状、修法选择等)依现行法源成立即可,不因无逐字原话驳回。
19
19
 
20
- 判断不收敛(同类问题反复、修理只增不减)可上呈;你的打回与上一轮相同、对方重交只换措辞,须上呈,不得再打回。修理 diff 自身按同尺复核。
20
+ 判断不收敛(同类问题反复、修理只增不减)可上呈;你的打回一轮轮完全一样、对方的重交也一轮轮只换措辞不换实质、转圈不止,须上呈;对方维持一次判词不算转圈。修理 diff 自身按同尺复核。
21
21
 
22
22
  衙门不是需求来源。弹章、施工方的注释与测试、你造的探针,都只是线索。判一条 finding 成立、开一条约束,判词须写明要它的那一句法,先看那句讲的是不是这一条;指不出的,按过度防御或加戏驳回。判词缺这一样,审刑院打回,符宝郎驳。对方按你处方加的东西,下轮同审。
23
23
 
@@ -6,6 +6,6 @@
6
6
  二、错封——封驳或所加约束指不出法源,或超出票面与陛下的话。
7
7
  三、事实错——判词所引代码事实、法源引文与源头不符。
8
8
 
9
- 三者皆无即 converged,一轮了结。判词少写一句而事实立得住,不是错;施工没做完,是大理寺封驳的理由,不是你打回判词的理由。打回与上一轮相同、对方只换措辞重交,上呈。
9
+ 三者皆无即 converged,一轮了结。判词少写一句而事实立得住,不是错;施工没做完,是大理寺封驳的理由,不是你打回判词的理由。
10
10
 
11
11
  调卷宗与取证、纪律依《审刑院法典》。合规则 `converged`;有错则 `continue`,逐条指出是哪一种错和你查到的原因;无法判断时 `escalate`。
@@ -386,109 +386,9 @@ export interface RoleHost {
386
386
  getCommands?(): Array<{ name: string }>;
387
387
  }
388
388
 
389
- /** Institutional sub-session seats (#518 §1). */
390
- export type InstitutionalSeat =
391
- | "gatekeeper"
392
- | "inspector"
393
- | "notary"
394
- | "auditor"
395
- | (string & {});
396
-
397
389
  /** Non-secret host-neutral seat model selection. Single truth source is RoleTurnModelConfig. */
398
390
  export type HostInstitutionalModelSelection = RoleTurnModelConfig;
399
391
 
400
- /** Usage statistics for institutional sub-session events and turns. */
401
- export type HostSessionUsage = {
402
- readonly input: number;
403
- readonly output: number;
404
- readonly cacheRead: number;
405
- readonly cacheWrite: number;
406
- readonly totalTokens: number;
407
- readonly cost: {
408
- readonly input: number;
409
- readonly output: number;
410
- readonly cacheRead: number;
411
- readonly cacheWrite: number;
412
- readonly total: number;
413
- };
414
- };
415
-
416
- /** Closed stream event union consumed by institutional callers (#518 §1③). */
417
- export type HostInstitutionalSessionEvent =
418
- | {
419
- readonly type: "message_end";
420
- readonly role: "assistant" | "user" | string;
421
- readonly message?: unknown;
422
- readonly usage?: HostSessionUsage;
423
- }
424
- | {
425
- readonly type: "turn_end";
426
- readonly stopReason?: string;
427
- }
428
- | {
429
- readonly type: "tool_call";
430
- readonly toolCallId: string;
431
- readonly toolName: string;
432
- readonly args?: unknown;
433
- }
434
- | {
435
- readonly type: "tool_result";
436
- readonly toolCallId: string;
437
- readonly toolName: string;
438
- readonly isError?: boolean;
439
- readonly details?: unknown;
440
- };
441
-
442
- /** Terminal result of an institutional assistant turn (#518 §1③). */
443
- export type HostAssistantTurnResult = {
444
- readonly text: string;
445
- readonly stopReason?: string;
446
- readonly errorMessage?: string;
447
- readonly usage?: HostSessionUsage;
448
- readonly messages?: readonly unknown[];
449
- };
450
-
451
- /**
452
- * Handle to an active institutional sub-session (#518 §1②).
453
- * Does not leak AgentSession, ModelRuntime, or Provider objects out of the adapter.
454
- */
455
- export interface HostInstitutionalSessionHandle {
456
- readonly sessionFile?: string;
457
- readonly sessionId?: string;
458
- prompt(text: string): Promise<HostAssistantTurnResult>;
459
- subscribe(listener: (event: HostInstitutionalSessionEvent) => void): () => void;
460
- abort(): void;
461
- close(): Promise<void>;
462
- }
463
-
464
- /** Open options for an institutional sub-session (#518 §1①). */
465
- export type HostInstitutionalSessionOptions = {
466
- readonly cwd: string;
467
- readonly selection: HostInstitutionalModelSelection;
468
- readonly systemPrompt: string;
469
- readonly tools?: readonly HostToolDefinition[];
470
- readonly customTools?: readonly unknown[];
471
- readonly noTools?: "all" | "builtin";
472
- readonly toolsAllowlist?: readonly string[];
473
- readonly agentDir?: string;
474
- readonly credentialScratchParent?: string;
475
- readonly signal?: AbortSignal;
476
- readonly idleRetry?: boolean;
477
- readonly sessionIdentity?: {
478
- readonly kind: string;
479
- readonly subject?: string;
480
- readonly parent?: { getSessionFile(): string | undefined };
481
- };
482
- readonly sessionManager?: unknown;
483
- };
484
-
485
- /** Host-neutral institutional sub-session open seam. */
486
- export interface InstitutionalSessionHost {
487
- openInstitutionalSession(
488
- options: HostInstitutionalSessionOptions,
489
- ): Promise<HostInstitutionalSessionHandle>;
490
- }
491
-
492
392
  /** Host-owned durable record session used by AK ledger placement. */
493
393
  export interface HostRecordSession {
494
394
  getSessionFile(): string | undefined;
@@ -24,12 +24,6 @@ import {
24
24
  } from "./activation-ledger.ts";
25
25
  import { readPackageMaterial } from "./session-opening-materials.ts";
26
26
  import { writeStderrJsonlRecord } from "./stderr-jsonl.ts";
27
- import {
28
- createToolExecutionObservationFace,
29
- systemToolExecutionObservationMonoNow,
30
- writeToolExecutionObservationRecord,
31
- type ToolExecutionObservationWriter,
32
- } from "./tool-execution-observation.ts";
33
27
  import {
34
28
  ENGINE_DETOUR_TOOL_NAME,
35
29
  ENGINE_MODEL_FLAG_NAME,
@@ -286,17 +280,6 @@ export type {
286
280
  ActivationSessionManager,
287
281
  ActivationSessionPointer,
288
282
  } from "./activation-ledger.ts";
289
- export {
290
- TOOL_EXECUTION_UPDATE_HEARTBEAT,
291
- TOOL_EXECUTION_UPDATE_THROTTLE_MS,
292
- createToolExecutionObservationFace,
293
- isProducingToolUpdate,
294
- systemToolExecutionObservationMonoNow,
295
- toolExecutionObservationRecordSchema,
296
- validateToolExecutionObservationRecord,
297
- writeToolExecutionObservationRecord,
298
- } from "./tool-execution-observation.ts";
299
- export type { ToolExecutionObservationRecord, ToolExecutionObservationWriter } from "./tool-execution-observation.ts";
300
283
  import {
301
284
  NOTARY_OUTPUT_TOOL,
302
285
  INSPECTOR_OUTPUT_TOOL,
@@ -477,11 +460,6 @@ export type RoleRuntimeDependencies = {
477
460
  loadNavigatorWorkContext?(options: { context: HostContext; role: string; phase: NavigatorPhase; getFlag?: (name: string) => unknown }): Promise<NavigatorWorkContext>;
478
461
  activationClock?(): string;
479
462
  activationTraceWriter?: (record: ActivationTraceRecord) => void | Promise<void>;
480
- /** Wall-clock ISO timestamps for tool-execution observation records; defaults to activationClock/Date. */
481
- toolExecutionObservationClock?(): string;
482
- /** Monotonic ms clock for update throttling; defaults to performance.now (not Date.now). */
483
- toolExecutionObservationMonoNow?(): number;
484
- toolExecutionObservationWriter?: ToolExecutionObservationWriter;
485
463
  };
486
464
 
487
465
  function abortContext(ctx: { abort(): void }): void {
@@ -1081,7 +1059,7 @@ export function createRoleRuntimeExtension(
1081
1059
  // terminating-tool rejections and mechanical delivery requests share two turns.
1082
1060
  let receiptDelivery = createReceiptDeliveryPolicy();
1083
1061
  let noReceiptRecorded = false;
1084
- // Public-run fetch observation (in-process-session statusAwareFetch face).
1062
+ // Public-run fetch observation.
1085
1063
  let priorFetch: typeof globalThis.fetch | undefined;
1086
1064
  let fetchWrapped = false;
1087
1065
  /** Envelope-owned: abort/teardown attendance without re-blocking the parent court (#959). */
@@ -1498,7 +1476,6 @@ export function createRoleRuntimeExtension(
1498
1476
  disposeNavigatorAttendanceNonBlocking(attendanceToDispose);
1499
1477
  pendingInfrastructureFailures.clear();
1500
1478
  pendingSubmissionNonPassByToolCallId.clear();
1501
- observationFace.reset();
1502
1479
  });
1503
1480
 
1504
1481
  const hostActions = {
@@ -1736,38 +1713,9 @@ export function createRoleRuntimeExtension(
1736
1713
 
1737
1714
  const clock = dependencies.activationClock ?? (() => new Date().toISOString());
1738
1715
  const writeTrace = dependencies.activationTraceWriter ?? writeActivationTraceRecord;
1739
- const observationFace = createToolExecutionObservationFace({
1740
- role: () => selectedRole,
1741
- admitted: () => admitted,
1742
- clock: dependencies.toolExecutionObservationClock ?? clock,
1743
- monoNow: dependencies.toolExecutionObservationMonoNow ?? systemToolExecutionObservationMonoNow,
1744
- write: dependencies.toolExecutionObservationWriter ?? writeToolExecutionObservationRecord,
1745
- });
1746
- // ExtensionRunner.emit catches ordinary handler throws, emits extension error, and continues.
1747
- // Observation plane failures must still hit the shared infrastructure termination path
1748
- // (abort + nonzero print/json exit) with the original cause before that swallow.
1749
- const observe = async (
1750
- run: () => void | Promise<void>,
1751
- ctx: HostContext,
1752
- ): Promise<void> => {
1753
- try {
1754
- await run();
1755
- } catch (error) {
1756
- failInfrastructure(error, ctx);
1757
- }
1758
- };
1759
- roleHost.on("tool_execution_start", async (event, ctx) => {
1760
- await observe(() => observationFace.onStart(event), ctx);
1761
- });
1762
- roleHost.on("tool_execution_update", async (event, ctx) => {
1763
- await observe(() => observationFace.onUpdate(event), ctx);
1764
- });
1765
- roleHost.on("tool_execution_end", async (event, ctx) => {
1766
- await observe(() => observationFace.onEnd(event), ctx);
1767
- });
1768
1716
 
1769
1717
  // Public Role run: record typed non-success HTTP for error evidence + v1 resume.
1770
- // Same observation owner as in-process-session statusAwareFetch → typed-provider-http
1718
+ // Same observation owner → typed-provider-http
1771
1719
  // sidecar (settlement already merges observation.httpStatus into knownFailure).
1772
1720
  // after_provider_response covers the success-path onResponse face; fetch wrap covers
1773
1721
  // non-2xx Responses where openai-completions throws before onResponse (#675).
@@ -1805,7 +1753,7 @@ export function createRoleRuntimeExtension(
1805
1753
  });
1806
1754
 
1807
1755
  roleHost.on("session_start", async (event, ctx) => {
1808
- // Scope fetch observation to this public run (in-process-session statusAwareFetch face).
1756
+ // Scope fetch observation to this public run.
1809
1757
  if (!fetchWrapped && typeof globalThis.fetch === "function") {
1810
1758
  priorFetch = globalThis.fetch.bind(globalThis);
1811
1759
  const underlying = priorFetch;
@@ -1827,7 +1775,7 @@ export function createRoleRuntimeExtension(
1827
1775
  provider,
1828
1776
  });
1829
1777
  } catch {
1830
- // Observation must not break the provider stream (same as in-process-session).
1778
+ // Observation must not break the provider stream.
1831
1779
  }
1832
1780
  }
1833
1781
  return response;
@@ -1842,7 +1790,6 @@ export function createRoleRuntimeExtension(
1842
1790
  collectorFirstDispatchDone = false;
1843
1791
  receiptDelivery = createReceiptDeliveryPolicy();
1844
1792
  noReceiptRecorded = false;
1845
- observationFace.reset();
1846
1793
  pendingNavigatorPresentation = undefined;
1847
1794
  pendingNavigatorSettlement = undefined;
1848
1795
  pendingInfrastructureFailures.clear();
@@ -353,7 +353,6 @@ export function appendSitianRecord(input: SitianRecordInput): RecordPointer {
353
353
  identity,
354
354
  ...(input.subject === undefined ? {} : { subject: input.subject }),
355
355
  ...(input.sessionParent === undefined ? {} : { sessionParent: input.sessionParent }),
356
- ...(input.priorEventId === undefined ? {} : { priorEventId: input.priorEventId }),
357
356
  timestamp,
358
357
  host,
359
358
  ...(input.source === undefined ? {} : { source: input.source }),
@@ -37,8 +37,6 @@ export type SitianRecord = {
37
37
  readonly subject?: SitianSubject | undefined;
38
38
  /** Parent session principal link / nesting origin. */
39
39
  readonly sessionParent?: string | undefined;
40
- /** Prior event identity in a submission ledger chain (S4; distinct from sessionParent). */
41
- readonly priorEventId?: string | undefined;
42
40
  readonly timestamp: string;
43
41
  readonly host: string;
44
42
  readonly source?: string | undefined;
@@ -65,7 +63,6 @@ export type SitianRecordInput = {
65
63
  readonly sessionParent?: string | undefined;
66
64
  /** Run owner for ticket provenance before a ticket is known. */
67
65
  readonly runDirectory?: string | undefined;
68
- readonly priorEventId?: string | undefined;
69
66
  readonly timestamp?: string | undefined;
70
67
  readonly host?: string | undefined;
71
68
  readonly source?: string | undefined;
@@ -146,7 +146,7 @@ async function submissionRecordFile(cwd: string, runId: string, scope: Submissio
146
146
  /**
147
147
  * Discriminated owned-row view:
148
148
  * - unknown run → file absent + empty owned (read APIs only)
149
- * - located ledger → file is string; prior/write consumers may build RecordPointer
149
+ * - located ledger → file is string; write consumers may build RecordPointer
150
150
  */
151
151
  type OwnedSubmissionRecords =
152
152
  | { readonly file: undefined; readonly owned: readonly [] }
@@ -491,11 +491,10 @@ export async function readLatestSubmissionOutcome(
491
491
  return undefined;
492
492
  }
493
493
 
494
- type LedgerState = { prior?: RecordPointer; sequence: number };
494
+ type LedgerState = { sequence: number };
495
495
 
496
496
  async function restoreState(cwd: string, runId: string, scope: SubmissionLedgerReadScope): Promise<LedgerState> {
497
497
  const located = await readOwnedSubmissionRecords(cwd, runId, scope);
498
- // Unknown-run empty set: no prior chain. Owned rows without a file are an internal bug.
499
498
  if (located.file === undefined) {
500
499
  if (located.owned.length !== 0) {
501
500
  throw new Error(
@@ -504,19 +503,8 @@ async function restoreState(cwd: string, runId: string, scope: SubmissionLedgerR
504
503
  }
505
504
  return { sequence: 0 };
506
505
  }
507
- const { file, owned } = located;
508
- const last = owned.at(-1);
506
+ const { owned } = located;
509
507
  return {
510
- ...(last === undefined
511
- ? {}
512
- : {
513
- prior: {
514
- identity: last.identity,
515
- recordFile: file,
516
- kind: last.kind,
517
- level: last.level,
518
- },
519
- }),
520
508
  sequence: owned.reduce((maximum, record) => {
521
509
  const payload = record.payload as Partial<SubmissionLedgerEvent> | undefined;
522
510
  return payload?.type === "candidate" && typeof payload.sequence === "number"
@@ -547,7 +535,7 @@ function homeFromHostContext(context: HostContext, home?: string): string | unde
547
535
 
548
536
  /**
549
537
  * #959: seal one accepted submission without a model tool call.
550
- * Same ledger row shape and priorEventId chain as the terminating-tool wrap.
538
+ * Same ledger row shape as the terminating-tool wrap.
551
539
  * Used when a prose-exit seat (navigator) harvests the final assistant text.
552
540
  */
553
541
  export async function sealAcceptedSubmission(options: {
@@ -561,15 +549,10 @@ export async function sealAcceptedSubmission(options: {
561
549
  const attemptId = attemptIdentity(options.context, runId);
562
550
  const sessionParent = sessionParentFromHostContext(options.context);
563
551
  const home = homeFromHostContext(options.context, options.home);
564
- const state = await restoreState(options.context.cwd, runId, {
565
- ...(home === undefined ? {} : { home }),
566
- ...(sessionParent === undefined ? {} : { sessionParent }),
567
- });
568
- const pointer = sitianReport({
552
+ sitianReport({
569
553
  level: "event",
570
554
  kind: "sealed",
571
555
  subject: { runId, attemptId },
572
- ...(state.prior === undefined ? {} : { priorEventId: state.prior.identity }),
573
556
  payload: {
574
557
  type: "sealed",
575
558
  attemptId,
@@ -582,7 +565,6 @@ export async function sealAcceptedSubmission(options: {
582
565
  ...(home !== undefined ? { home } : {}),
583
566
  ...(sessionParent === undefined ? {} : { sessionParent }),
584
567
  });
585
- state.prior = pointer;
586
568
  }
587
569
 
588
570
  /**
@@ -611,32 +593,29 @@ export function createSubmissionLedgerHost(
611
593
  states.set(runId, pending);
612
594
  return pending;
613
595
  })();
614
- const appendFor = (state: LedgerState, context: HostContext, runId: string, attemptId: string, event: SubmissionLedgerEvent): RecordPointer => {
596
+ const appendFor = (context: HostContext, runId: string, attemptId: string, event: SubmissionLedgerEvent): RecordPointer => {
615
597
  const home = resolveHomeFromContext(context);
616
598
  const sessionParent = sessionParentFromHostContext(context);
617
- const pointer = sitianReport({
599
+ return sitianReport({
618
600
  level: "event",
619
601
  kind: event.type,
620
602
  subject: { runId, attemptId },
621
- ...(state.prior === undefined ? {} : { priorEventId: state.prior.identity }),
622
603
  payload: event,
623
604
  source: "role-runtime",
624
605
  cwd: context.cwd,
625
606
  ...(home !== undefined ? { home } : {}),
626
607
  ...(sessionParent === undefined ? {} : { sessionParent }),
627
608
  });
628
- state.prior = pointer;
629
- return pointer;
630
609
  };
631
610
 
632
611
  host.on("turn_end", async (event, context) => {
633
612
  try {
634
613
  const runId = runIdentity(context);
635
614
  const attemptId = attemptIdentity(context, runId);
636
- const state = await stateFor(context, runId);
637
615
  const calls = event.calls.map(({ toolCallId: id, toolName: name }) => ({ id, name }));
638
616
  if (calls.length > 0) {
639
- appendFor(state, context, runId, attemptId, { type: "roundContext", attemptId, calls });
617
+ await stateFor(context, runId);
618
+ appendFor(context, runId, attemptId, { type: "roundContext", attemptId, calls });
640
619
  }
641
620
  } catch (error) {
642
621
  failInfrastructure(error, context);
@@ -663,7 +642,7 @@ export function createSubmissionLedgerHost(
663
642
  const runId = runIdentity(context);
664
643
  const attemptId = attemptIdentity(context, runId);
665
644
  const state = await stateFor(context, runId);
666
- const append = (event: SubmissionLedgerEvent) => appendFor(state, context, runId, attemptId, event);
645
+ const append = (event: SubmissionLedgerEvent) => appendFor(context, runId, attemptId, event);
667
646
  // #541 / #575: shared infra-declaration fail lives on the ledger seam.
668
647
  // #641 chain②: seats may bounce a misdeclared infrastructure failure
669
648
  // as correctable (2.1/2.2/2.3 keep paths).