@akagilnc/pi-workflow-roles 0.1.3391 → 0.1.3403

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.
@@ -8584,16 +8584,8 @@ function runIdentity(context) {
8584
8584
  if (typeof headerId === "string" && headerId.length > 0) return headerId;
8585
8585
  throw new Error("\u63D0\u4EA4\u8D26\u9700\u8981\u5DF2\u53D7\u7406\u7684 run \u8EAB\u4EFD");
8586
8586
  }
8587
- function latestUserAttemptId(entries) {
8588
- const ordered = [...entries];
8589
- for (let index = ordered.length - 1; index >= 0; index -= 1) {
8590
- const entry = ordered[index];
8591
- if (entry?.message?.role === "user" && typeof entry.id === "string") return entry.id;
8592
- }
8593
- return void 0;
8594
- }
8595
8587
  function attemptIdentity(context, runId) {
8596
- return latestUserAttemptId(context.sessionManager.getEntries?.() ?? []) ?? context.sessionManager.getHeader?.()?.id ?? context.sessionManager.getLeafId?.() ?? `${runId}:initial`;
8588
+ return context.sessionManager.getHeader?.()?.id ?? context.sessionManager.getLeafId?.() ?? `${runId}:initial`;
8597
8589
  }
8598
8590
  function submissionRecordFile(cwd, runId, home) {
8599
8591
  const ledgerHome = resolveActivationLedgerHome(home);
@@ -24326,14 +24326,6 @@ var init_run_terminal_artifacts = __esm({
24326
24326
  });
24327
24327
 
24328
24328
  // src/submission-ledger.ts
24329
- function latestUserAttemptId(entries) {
24330
- const ordered = [...entries];
24331
- for (let index = ordered.length - 1; index >= 0; index -= 1) {
24332
- const entry = ordered[index];
24333
- if (entry?.message?.role === "user" && typeof entry.id === "string") return entry.id;
24334
- }
24335
- return void 0;
24336
- }
24337
24329
  function isAcceptedProjection(value) {
24338
24330
  if (typeof value !== "object" || value === null) return false;
24339
24331
  const candidate = value;
@@ -24372,17 +24364,13 @@ async function readSealedSubmission(cwd, runId, home) {
24372
24364
  }
24373
24365
  return void 0;
24374
24366
  }
24375
- async function readAuditEscalationSubmission(cwd, runId, home, currentAttemptId) {
24367
+ async function readAuditEscalationSubmission(cwd, runId, home) {
24376
24368
  const { owned } = await readOwnedSubmissionRecords(cwd, runId, home);
24377
- const latestAttemptId = currentAttemptId ?? owned.at(-1)?.subject?.attemptId;
24378
- if (typeof latestAttemptId !== "string") return void 0;
24379
24369
  for (let index = owned.length - 1; index >= 0; index -= 1) {
24380
24370
  const record4 = owned[index];
24381
- if (record4?.subject?.attemptId !== latestAttemptId) continue;
24382
24371
  if (record4?.kind !== "outcome") continue;
24383
24372
  const payload = record4.payload;
24384
- if (payload?.type !== "outcome") continue;
24385
- if (payload.outcome !== "audit-escalation") return void 0;
24373
+ if (payload?.type !== "outcome" || payload.outcome !== "audit-escalation") continue;
24386
24374
  if (isAuditEscalationTerminalProjection(payload.projection)) return payload.projection;
24387
24375
  }
24388
24376
  return void 0;
@@ -24956,27 +24944,28 @@ function sealedLedgerHome(admitted) {
24956
24944
  async function sealedLedgerOutcome(admitted) {
24957
24945
  return readSealedSubmission(admitted.projectRoot, admitted.runId, sealedLedgerHome(admitted));
24958
24946
  }
24959
- async function hasSealedAcceptedProjection(admitted) {
24960
- return await sealedLedgerOutcome(admitted) !== void 0;
24961
- }
24962
- async function auditEscalationLedgerOutcome(admitted, role, authority) {
24963
- let currentAttemptId;
24964
- if (role === "coder" || role === "fixer") {
24965
- const entries = await readBoundSessionEntries(coordinatesFromAdmitted(authority, admitted).sessionFile);
24966
- currentAttemptId = latestUserAttemptId(entries);
24947
+ async function sealedAcceptanceRedispatchDisposition(admitted) {
24948
+ try {
24949
+ if (await sealedLedgerOutcome(admitted) !== void 0) {
24950
+ return { kind: "block", reason: "sealed-accepted" };
24951
+ }
24952
+ return { kind: "allow" };
24953
+ } catch (cause) {
24954
+ return { kind: "block", reason: "authority-failed", cause };
24967
24955
  }
24956
+ }
24957
+ async function auditEscalationLedgerOutcome(admitted, role) {
24968
24958
  const projection = await readAuditEscalationSubmission(
24969
24959
  admitted.projectRoot,
24970
24960
  admitted.runId,
24971
- sealedLedgerHome(admitted),
24972
- currentAttemptId
24961
+ sealedLedgerHome(admitted)
24973
24962
  );
24974
24963
  if (projection?.role !== role) return void 0;
24975
24964
  return projection;
24976
24965
  }
24977
- async function closedLedgerOutcome(admitted, role, authority) {
24966
+ async function closedLedgerOutcome(admitted, role) {
24978
24967
  const sealed = await sealedLedgerOutcome(admitted);
24979
- return sealed?.role === role ? sealed : auditEscalationLedgerOutcome(admitted, role, authority);
24968
+ return sealed?.role === role ? sealed : auditEscalationLedgerOutcome(admitted, role);
24980
24969
  }
24981
24970
  function coordinatesFromAdmitted(authority, admitted) {
24982
24971
  return authority.decode(admitted.principal);
@@ -26301,7 +26290,7 @@ async function readLawfulJudgeRoleOutcome(admitted, authority) {
26301
26290
  decisiveFacts: judgeDecisiveFacts(details, sealed.status)
26302
26291
  };
26303
26292
  }
26304
- return auditEscalationLedgerOutcome(admitted, "judge", authority);
26293
+ return auditEscalationLedgerOutcome(admitted, "judge");
26305
26294
  }
26306
26295
  async function settleLawfulJudgeTerminalResult(admitted, authority) {
26307
26296
  const roleOutcome = await readLawfulJudgeRoleOutcome(admitted, authority);
@@ -26328,7 +26317,7 @@ async function trySettleJudgeTerminalResult(admitted, authority) {
26328
26317
  return settleLawfulJudgeTerminalResult(admitted, authority);
26329
26318
  }
26330
26319
  async function settleLawfulCoderTerminalResult(admitted, authority, options = {}) {
26331
- const ledgerOutcome = await closedLedgerOutcome(admitted, "coder", authority);
26320
+ const ledgerOutcome = await closedLedgerOutcome(admitted, "coder");
26332
26321
  if (ledgerOutcome === void 0) return void 0;
26333
26322
  let roleOutcome = ledgerOutcome;
26334
26323
  let output;
@@ -26448,7 +26437,7 @@ async function publishFixerArtifacts(admitted, roleOutcome, coordinates, options
26448
26437
  ];
26449
26438
  }
26450
26439
  async function settleLawfulFixerTerminalResult(admitted, authority, options) {
26451
- const ledgerOutcome = await closedLedgerOutcome(admitted, "fixer", authority);
26440
+ const ledgerOutcome = await closedLedgerOutcome(admitted, "fixer");
26452
26441
  if (ledgerOutcome === void 0) return void 0;
26453
26442
  let roleOutcome = ledgerOutcome;
26454
26443
  let output;
@@ -26655,7 +26644,7 @@ async function settleLawfulDoctorTerminalResult(admitted, authority) {
26655
26644
  const { sessionDirectory, sessionFile } = coordinates;
26656
26645
  const entries = await readLawfulSettlementEntries(sessionFile) ?? [];
26657
26646
  if (sealed?.role !== "doctor") {
26658
- const escalation = await auditEscalationLedgerOutcome(admitted, "doctor", authority);
26647
+ const escalation = await auditEscalationLedgerOutcome(admitted, "doctor");
26659
26648
  if (escalation === void 0) return void 0;
26660
26649
  const artifacts2 = await publishDoctorArtifacts(admitted, escalation, coordinates);
26661
26650
  return withOptionalGateProjection(
@@ -26719,7 +26708,7 @@ async function settleLawfulSeatAcceptedTerminalResult(admitted, authority, spec)
26719
26708
  const coordinates = coordinatesFromAdmitted(authority, admitted);
26720
26709
  const { sessionDirectory, sessionFile } = coordinates;
26721
26710
  const entries = await readLawfulSettlementEntries(sessionFile) ?? [];
26722
- const roleOutcome = await closedLedgerOutcome(admitted, spec.role, authority);
26711
+ const roleOutcome = await closedLedgerOutcome(admitted, spec.role);
26723
26712
  if (roleOutcome?.kind === "audit_escalation") {
26724
26713
  const navigator2 = extractNavigatorFact(entries);
26725
26714
  return withOptionalGateProjection(
@@ -27955,36 +27944,21 @@ async function runWithAutoResumeLoop(options) {
27955
27944
  return result2;
27956
27945
  }
27957
27946
  }
27958
- if (options.shouldStopAutoResume !== void 0) {
27959
- let failClosed;
27960
- let sealedStop = false;
27961
- try {
27962
- sealedStop = await options.shouldStopAutoResume();
27963
- } catch (authorityError) {
27964
- failClosed = {
27965
- cause: authorityError,
27966
- endReason: "sealed-acceptance authority failed closed"
27967
- };
27968
- }
27969
- if (failClosed === void 0 && sealedStop) {
27970
- if (result2 !== void 0) {
27971
- const terminal = result2.terminal;
27972
- if (terminal !== void 0) presentTerminal(terminal, options.io);
27947
+ if (options.sealedAcceptanceDisposition !== void 0) {
27948
+ const disposition = await options.sealedAcceptanceDisposition();
27949
+ if (disposition.kind === "block") {
27950
+ if (disposition.reason === "sealed-accepted" && result2 !== void 0) {
27951
+ const terminal2 = result2.terminal;
27952
+ if (terminal2 !== void 0) presentTerminal(terminal2, options.io);
27973
27953
  return result2;
27974
27954
  }
27975
- failClosed = {
27976
- cause: lastThrownError,
27977
- endReason: "sealed accepted projection already present"
27978
- };
27979
- }
27980
- if (failClosed !== void 0) {
27981
27955
  const terminal = dispatchExceptionFailureTerminal({
27982
27956
  role: options.admitted.role,
27983
27957
  runId: options.admitted.runId,
27984
- causeError: failClosed.cause,
27958
+ causeError: disposition.reason === "authority-failed" ? disposition.cause : lastThrownError,
27985
27959
  errorFiles: retainedErrorFiles,
27986
27960
  autoResumeAttempts,
27987
- endReason: failClosed.endReason,
27961
+ endReason: disposition.reason === "authority-failed" ? "sealed-acceptance authority failed closed" : "sealed accepted projection already present",
27988
27962
  everyAttemptThrew
27989
27963
  });
27990
27964
  await finalizeExceptionRunBestEffort(options.admitted.runDirectory, options.io);
@@ -28338,7 +28312,7 @@ async function runPostAdmissionResumable(input) {
28338
28312
  autoResumeLimit: env.autoResumeLimit,
28339
28313
  buildInitialPayload: buildInitialRequest,
28340
28314
  buildResumePayload: buildResumeRequest,
28341
- shouldStopAutoResume: async () => hasSealedAcceptedProjection(admitted),
28315
+ sealedAcceptanceDisposition: () => sealedAcceptanceRedispatchDisposition(admitted),
28342
28316
  dispatch: (request, lease, _isFirst, attemptIo) => dispatchPostAdmissionTurn({
28343
28317
  admitted,
28344
28318
  env: {
@@ -28370,22 +28344,15 @@ async function runPostAdmissionManualResume(input) {
28370
28344
  };
28371
28345
  }
28372
28346
  } catch (error) {
28373
- let failClosed;
28374
- try {
28375
- if (await hasSealedAcceptedProjection(admitted)) {
28376
- failClosed = { cause: error };
28377
- }
28378
- } catch (authorityError) {
28379
- failClosed = { cause: authorityError };
28380
- }
28381
- if (failClosed !== void 0) {
28347
+ const disposition = await sealedAcceptanceRedispatchDisposition(admitted);
28348
+ if (disposition.kind === "block") {
28382
28349
  return await presentControlledFailure2(
28383
28350
  admitted,
28384
28351
  {
28385
28352
  timedOut: false,
28386
28353
  code: null,
28387
28354
  stderr: "",
28388
- thrown: failClosed.cause
28355
+ thrown: disposition.reason === "authority-failed" ? disposition.cause : error
28389
28356
  },
28390
28357
  adapters,
28391
28358
  env.principalAuthority,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.3391",
3
+ "version": "0.1.3403",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -31,7 +31,11 @@ import {
31
31
  } from "./run-lifecycle.ts";
32
32
  import { parseAutoResumeLimit } from "./config.ts";
33
33
  import { isLawfulTypedTerminalOutcome, formatTerminalResult, type TerminalArtifactRef, type TerminalResult, type TerminalRoleName } from "./terminal.ts";
34
- import { presentFailureTerminal, presentStructuralRejection } from "./settlement.ts";
34
+ import {
35
+ presentFailureTerminal,
36
+ presentStructuralRejection,
37
+ type SealedAcceptanceRedispatchDisposition,
38
+ } from "./settlement.ts";
35
39
  import type { CliIo } from "./cli-io.ts";
36
40
 
37
41
  const dummyIo: CliIo = { stdout: () => {}, stderr: () => {} };
@@ -343,11 +347,12 @@ export async function runWithAutoResumeLoop<
343
347
  buildResumePayload: () => TPayload;
344
348
  dispatch: (payload: TPayload, lease: RunWriterLease, isFirst: boolean, attemptIo: CliIo) => Promise<T>;
345
349
  /**
346
- * After a non-lawful terminal or dispatch throw, stop further auto-resume when a unique sealed
347
- * accepted projection is already readable (publication miss must not redispatch
348
- * and destroy the sealed read — #648 / #599 alignment).
350
+ * After a non-lawful terminal or dispatch throw, consult settlement-owned
351
+ * sealed-acceptance redispatch disposition (#672 / ADR 0080). Publication
352
+ * miss must not redispatch and destroy the sealed read (#648 / #599).
353
+ * Loop presents entry-specific terminals; it must not rebuild the gate.
349
354
  */
350
- shouldStopAutoResume?: () => Promise<boolean>;
355
+ sealedAcceptanceDisposition?: () => Promise<SealedAcceptanceRedispatchDisposition>;
351
356
  }): Promise<T> {
352
357
  // #422 single-point resolution + domain validation. NaN would bypass every
353
358
  // `attempts >= limit` comparison (always false) — reject here, before any dispatch.
@@ -431,42 +436,30 @@ export async function runWithAutoResumeLoop<
431
436
  }
432
437
  }
433
438
 
434
- // One sealed ledger authority before any redispatch (#648): shared for
435
- // non-lawful return and direct throw. Authority throw fail-closes with
436
- // preserved cause — never wash into unsealed redispatch. Only the sealed=true
437
- // projection differs (present returned terminal vs throw-path synthetic).
438
- // Fail-closed decision is independent of cause value: `throw undefined` is
439
- // legal JS and must not fail open. One cause + endReason → one presentation.
440
- if (options.shouldStopAutoResume !== undefined) {
441
- let failClosed: { cause: unknown; endReason: string } | undefined;
442
- let sealedStop = false;
443
- try {
444
- sealedStop = await options.shouldStopAutoResume();
445
- } catch (authorityError) {
446
- failClosed = {
447
- cause: authorityError,
448
- endReason: "sealed-acceptance authority failed closed",
449
- };
450
- }
451
- if (failClosed === undefined && sealedStop) {
452
- if (result !== undefined) {
439
+ // Settlement-owned sealed disposition before any redispatch (#648 / #672):
440
+ // shared for non-lawful return and direct throw. Only entry presentation
441
+ // differs (present returned terminal vs throw-path synthetic).
442
+ if (options.sealedAcceptanceDisposition !== undefined) {
443
+ const disposition = await options.sealedAcceptanceDisposition();
444
+ if (disposition.kind === "block") {
445
+ if (disposition.reason === "sealed-accepted" && result !== undefined) {
453
446
  const terminal = (result as { terminal?: TerminalResult }).terminal;
454
447
  if (terminal !== undefined) presentTerminal(terminal, options.io);
455
448
  return result;
456
449
  }
457
- failClosed = {
458
- cause: lastThrownError,
459
- endReason: "sealed accepted projection already present",
460
- };
461
- }
462
- if (failClosed !== undefined) {
463
450
  const terminal = dispatchExceptionFailureTerminal({
464
451
  role: options.admitted.role,
465
452
  runId: options.admitted.runId,
466
- causeError: failClosed.cause,
453
+ causeError:
454
+ disposition.reason === "authority-failed"
455
+ ? disposition.cause
456
+ : lastThrownError,
467
457
  errorFiles: retainedErrorFiles,
468
458
  autoResumeAttempts,
469
- endReason: failClosed.endReason,
459
+ endReason:
460
+ disposition.reason === "authority-failed"
461
+ ? "sealed-acceptance authority failed closed"
462
+ : "sealed accepted projection already present",
470
463
  everyAttemptThrew,
471
464
  });
472
465
  await finalizeExceptionRunBestEffort(options.admitted.runDirectory, options.io);
@@ -57,7 +57,7 @@ import {
57
57
  resolveAuditedRunnerFailureResolution,
58
58
  resolveControlledFailureResumeObservation,
59
59
  settleFailureTerminalResult,
60
- hasSealedAcceptedProjection,
60
+ sealedAcceptanceRedispatchDisposition,
61
61
  } from "./settlement.ts";
62
62
  import type { CliIo } from "./cli-io.ts";
63
63
  import type { AdmittedRoleInvocation } from "./invocation.ts";
@@ -547,8 +547,8 @@ export async function runPostAdmissionResumable<
547
547
  autoResumeLimit: env.autoResumeLimit,
548
548
  buildInitialPayload: buildInitialRequest,
549
549
  buildResumePayload: buildResumeRequest,
550
- shouldStopAutoResume: async () =>
551
- hasSealedAcceptedProjection(admitted),
550
+ sealedAcceptanceDisposition: () =>
551
+ sealedAcceptanceRedispatchDisposition(admitted),
552
552
  dispatch: (request, lease, _isFirst, attemptIo) =>
553
553
  dispatchPostAdmissionTurn({
554
554
  admitted,
@@ -614,27 +614,21 @@ export async function runPostAdmissionManualResume<
614
614
  };
615
615
  }
616
616
  } catch (error) {
617
- // Sealed accepted + publication/settle throw must fail closed without redispatch
618
- // (#648 / #599): do not treat "sealed + publish threw" as "not sealed".
619
- // Ledger authority failure also fail-closes with preserved cause (never wash to unsealed).
620
- // Fail-closed decision is independent of cause value: `throw undefined` is legal JS
621
- // and must not fail open. One cause → one presentation (settle vs authority).
622
- let failClosed: { cause: unknown } | undefined;
623
- try {
624
- if (await hasSealedAcceptedProjection(admitted)) {
625
- failClosed = { cause: error };
626
- }
627
- } catch (authorityError) {
628
- failClosed = { cause: authorityError };
629
- }
630
- if (failClosed !== undefined) {
617
+ // Settlement-owned sealed disposition (#648 / #599 / #672): sealed accepted +
618
+ // publication/settle throw fail closed without redispatch; authority failure
619
+ // preserves true cause. Manual resume only presents — does not rebuild the gate.
620
+ const disposition = await sealedAcceptanceRedispatchDisposition(admitted);
621
+ if (disposition.kind === "block") {
631
622
  return (await presentControlledFailure(
632
623
  admitted,
633
624
  {
634
625
  timedOut: false,
635
626
  code: null,
636
627
  stderr: "",
637
- thrown: failClosed.cause,
628
+ thrown:
629
+ disposition.reason === "authority-failed"
630
+ ? disposition.cause
631
+ : error,
638
632
  },
639
633
  adapters,
640
634
  env.principalAuthority,
@@ -13,7 +13,6 @@ import {
13
13
  } from "../analyst-gate-cycles-read.ts";
14
14
  import { readSitianRecords, resolveSitianRecordPath, sitianReport } from "../sitian-facade.ts";
15
15
  import {
16
- latestUserAttemptId,
17
16
  readAuditEscalationSubmission,
18
17
  readLatestSubmissionOutcome,
19
18
  readSealedSubmission,
@@ -164,32 +163,41 @@ async function sealedLedgerOutcome(admitted: AdmittedRoleInvocation): Promise<Ex
164
163
  }
165
164
 
166
165
  /**
167
- * Shared sealed-accepted detection for all resumable adapters (#648).
168
- * Ledger projection is the sole authority — not optional per-role adapter wiring.
166
+ * Shared sealed-acceptance redispatch disposition for resume entrypoints
167
+ * (#648 sealed authority; #672 / ADR 0080 single-settlement-disposition).
168
+ * Owns the fail-closed gate auto and manual resume previously rebuilt beside
169
+ * the shared sealed query: sealed → block; authority throw → block with
170
+ * preserved cause; otherwise allow. Callers present entry-specific terminals;
171
+ * they must not re-derive this judgment. Ledger projection remains the sole
172
+ * seal truth — this is disposition over that read, not a second state.
169
173
  */
170
- export async function hasSealedAcceptedProjection(
174
+ export type SealedAcceptanceRedispatchDisposition =
175
+ | { readonly kind: "allow" }
176
+ | { readonly kind: "block"; readonly reason: "sealed-accepted" }
177
+ | { readonly kind: "block"; readonly reason: "authority-failed"; readonly cause: unknown };
178
+
179
+ export async function sealedAcceptanceRedispatchDisposition(
171
180
  admitted: AdmittedRoleInvocation,
172
- ): Promise<boolean> {
173
- // Ledger authority must not wash read failure into "unsealed" (#648).
174
- // Callers treat throw as fail-closed: preserve true cause, never redispatch.
175
- return (await sealedLedgerOutcome(admitted)) !== undefined;
181
+ ): Promise<SealedAcceptanceRedispatchDisposition> {
182
+ try {
183
+ if ((await sealedLedgerOutcome(admitted)) !== undefined) {
184
+ return { kind: "block", reason: "sealed-accepted" };
185
+ }
186
+ return { kind: "allow" };
187
+ } catch (cause) {
188
+ // Ledger authority must not wash read failure into "unsealed" (#648).
189
+ return { kind: "block", reason: "authority-failed", cause };
190
+ }
176
191
  }
177
192
 
178
193
  async function auditEscalationLedgerOutcome(
179
194
  admitted: AdmittedRoleInvocation,
180
195
  role: TerminalRoleName,
181
- authority: DurablePrincipalAuthority,
182
196
  ): Promise<Extract<TerminalRoleOutcome, { kind: "audit_escalation" }> | undefined> {
183
- let currentAttemptId: string | undefined;
184
- if (role === "coder" || role === "fixer") {
185
- const entries = await readBoundSessionEntries(coordinatesFromAdmitted(authority, admitted).sessionFile);
186
- currentAttemptId = latestUserAttemptId(entries);
187
- }
188
197
  const projection = await readAuditEscalationSubmission(
189
198
  admitted.projectRoot,
190
199
  admitted.runId,
191
200
  sealedLedgerHome(admitted),
192
- currentAttemptId,
193
201
  );
194
202
  if (projection?.role !== role) return undefined;
195
203
  return projection;
@@ -198,12 +206,11 @@ async function auditEscalationLedgerOutcome(
198
206
  async function closedLedgerOutcome(
199
207
  admitted: AdmittedRoleInvocation,
200
208
  role: TerminalRoleName,
201
- authority: DurablePrincipalAuthority,
202
209
  ): Promise<Extract<TerminalRoleOutcome, { kind: "accepted" | "audit_escalation" }> | undefined> {
203
210
  const sealed = await sealedLedgerOutcome(admitted);
204
211
  return sealed?.role === role
205
212
  ? sealed
206
- : auditEscalationLedgerOutcome(admitted, role, authority);
213
+ : auditEscalationLedgerOutcome(admitted, role);
207
214
  }
208
215
 
209
216
  /** Transitional host-session reads remain only for non-sealed failure and audit evidence. */
@@ -2513,7 +2520,7 @@ export async function readLawfulJudgeRoleOutcome(
2513
2520
  };
2514
2521
  }
2515
2522
  // Non-final: consume ledger audit-escalation projection (no JSONL accepted rebuild).
2516
- return auditEscalationLedgerOutcome(admitted, "judge", authority);
2523
+ return auditEscalationLedgerOutcome(admitted, "judge");
2517
2524
  }
2518
2525
 
2519
2526
  /**
@@ -2590,7 +2597,7 @@ async function settleLawfulCoderTerminalResult(
2590
2597
  readonly methodProvenance?: PackagedMethodSkillProvenance;
2591
2598
  } = {},
2592
2599
  ): Promise<TerminalResult | undefined> {
2593
- const ledgerOutcome = await closedLedgerOutcome(admitted, "coder", authority);
2600
+ const ledgerOutcome = await closedLedgerOutcome(admitted, "coder");
2594
2601
  if (ledgerOutcome === undefined) return undefined;
2595
2602
  let roleOutcome: TerminalRoleOutcome = ledgerOutcome;
2596
2603
  let output: CoderOutput | undefined;
@@ -2778,7 +2785,7 @@ async function settleLawfulFixerTerminalResult(
2778
2785
  readonly methodSkillConfiguredPath: string;
2779
2786
  },
2780
2787
  ): Promise<TerminalResult | undefined> {
2781
- const ledgerOutcome = await closedLedgerOutcome(admitted, "fixer", authority);
2788
+ const ledgerOutcome = await closedLedgerOutcome(admitted, "fixer");
2782
2789
  if (ledgerOutcome === undefined) return undefined;
2783
2790
  let roleOutcome: TerminalRoleOutcome = ledgerOutcome;
2784
2791
  let output: FixerOutput | undefined;
@@ -3071,7 +3078,7 @@ async function settleLawfulDoctorTerminalResult(
3071
3078
  const { sessionDirectory, sessionFile } = coordinates;
3072
3079
  const entries = await readLawfulSettlementEntries(sessionFile) ?? [];
3073
3080
  if (sealed?.role !== "doctor") {
3074
- const escalation = await auditEscalationLedgerOutcome(admitted, "doctor", authority);
3081
+ const escalation = await auditEscalationLedgerOutcome(admitted, "doctor");
3075
3082
  if (escalation === undefined) return undefined;
3076
3083
  const artifacts = await publishDoctorArtifacts(admitted, escalation, coordinates);
3077
3084
  return withOptionalGateProjection(
@@ -3196,7 +3203,7 @@ async function settleLawfulSeatAcceptedTerminalResult(
3196
3203
  const coordinates = coordinatesFromAdmitted(authority, admitted);
3197
3204
  const { sessionDirectory, sessionFile } = coordinates;
3198
3205
  const entries = await readLawfulSettlementEntries(sessionFile) ?? [];
3199
- const roleOutcome = await closedLedgerOutcome(admitted, spec.role as TerminalRoleName, authority);
3206
+ const roleOutcome = await closedLedgerOutcome(admitted, spec.role as TerminalRoleName);
3200
3207
  if (roleOutcome?.kind === "audit_escalation") {
3201
3208
  const navigator = extractNavigatorFact(entries);
3202
3209
  return withOptionalGateProjection(
@@ -56,22 +56,8 @@ function runIdentity(context: HostContext): string {
56
56
  throw new Error("提交账需要已受理的 run 身份");
57
57
  }
58
58
 
59
- export function latestUserAttemptId(
60
- entries: Iterable<{ readonly id?: unknown; readonly message?: { readonly role?: unknown } }>,
61
- ): string | undefined {
62
- const ordered = [...entries];
63
- for (let index = ordered.length - 1; index >= 0; index -= 1) {
64
- const entry = ordered[index];
65
- if (entry?.message?.role === "user" && typeof entry.id === "string") return entry.id;
66
- }
67
- return undefined;
68
- }
69
-
70
59
  function attemptIdentity(context: HostContext, runId: string): string {
71
- return latestUserAttemptId(context.sessionManager.getEntries?.() ?? [])
72
- ?? context.sessionManager.getHeader?.()?.id
73
- ?? context.sessionManager.getLeafId?.()
74
- ?? `${runId}:initial`;
60
+ return context.sessionManager.getHeader?.()?.id ?? context.sessionManager.getLeafId?.() ?? `${runId}:initial`;
75
61
  }
76
62
 
77
63
  function isAcceptedProjection(value: unknown): value is Extract<TerminalRoleOutcome, { kind: "accepted" }> {
@@ -139,18 +125,13 @@ export async function readAuditEscalationSubmission(
139
125
  cwd: string,
140
126
  runId: string,
141
127
  home?: string,
142
- currentAttemptId?: string,
143
128
  ): Promise<AuditEscalationSubmissionProjection | undefined> {
144
129
  const { owned } = await readOwnedSubmissionRecords(cwd, runId, home);
145
- const latestAttemptId = currentAttemptId ?? (owned.at(-1)?.subject as { attemptId?: unknown } | undefined)?.attemptId;
146
- if (typeof latestAttemptId !== "string") return undefined;
147
130
  for (let index = owned.length - 1; index >= 0; index -= 1) {
148
131
  const record = owned[index];
149
- if ((record?.subject as { attemptId?: unknown } | undefined)?.attemptId !== latestAttemptId) continue;
150
132
  if (record?.kind !== "outcome") continue;
151
133
  const payload = record.payload as Partial<Extract<SubmissionLedgerEvent, { type: "outcome" }>> | undefined;
152
- if (payload?.type !== "outcome") continue;
153
- if (payload.outcome !== "audit-escalation") return undefined;
134
+ if (payload?.type !== "outcome" || payload.outcome !== "audit-escalation") continue;
154
135
  if (isAuditEscalationTerminalProjection(payload.projection)) return payload.projection;
155
136
  }
156
137
  return undefined;