@akagilnc/pi-workflow-roles 0.1.5483 → 0.1.5571

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 (112) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/acp-host/production-host.js +6312 -6376
  4. package/dist/analyst-gate-cycles-read.js +28 -78
  5. package/dist/analyst-ledger.js +26 -42
  6. package/dist/analyst-metric-families/acceptance-success-rework.js +25 -1
  7. package/dist/analyst-metric-families/round-timeline.js +2 -5
  8. package/dist/archivist-record-entry.js +4 -3
  9. package/dist/archivist-record-pointer.js +71 -36
  10. package/dist/atomic-write.js +2 -2
  11. package/dist/auditor-dossier-tool.js +11 -6
  12. package/dist/auditor-soul.js +5 -12
  13. package/dist/collector-config.js +6 -5
  14. package/dist/doctor-evidence.js +8 -4
  15. package/dist/engine-detour-usage.js +8 -22
  16. package/dist/headless-host/production-host.js +5969 -6011
  17. package/dist/host-descriptions.js +0 -4
  18. package/dist/host-session-record.js +266 -267
  19. package/dist/ledger-session-read.js +5 -0
  20. package/dist/migrate-book-topology.js +1369 -722
  21. package/dist/navigator-public-session.js +13 -17
  22. package/dist/notary-source-run.js +8 -16
  23. package/dist/packaged-role-registry.js +5 -56
  24. package/dist/pi/durable-principal.js +2 -3
  25. package/dist/pi/role-turn-host.js +79 -15
  26. package/dist/public-cli/auto-resume.js +8 -47
  27. package/dist/public-cli/instruction-seat-run.js +9 -7
  28. package/dist/public-cli/invocation.js +67 -100
  29. package/dist/public-cli/main.js +2689 -2532
  30. package/dist/public-cli/post-admission.js +96 -55
  31. package/dist/public-cli/run-lifecycle.js +44 -100
  32. package/dist/public-cli/settlement.js +184 -429
  33. package/dist/public-cli/terminal.js +0 -12
  34. package/dist/role-run-placement.js +53 -16
  35. package/dist/role-run-relocation.js +111 -52
  36. package/dist/run-dossier-files.js +30 -0
  37. package/dist/run-dossier.js +322 -0
  38. package/dist/run-terminal-artifacts.js +69 -202
  39. package/dist/run-ticket-number.js +49 -7
  40. package/dist/session-assistant-usage.js +9 -18
  41. package/dist/session-identity.js +49 -19
  42. package/dist/sitian-appender.js +29 -18
  43. package/dist/sitian-facade.js +11 -0
  44. package/dist/sitian-reader.js +44 -29
  45. package/dist/submission-gate.js +1 -1
  46. package/dist/submission-ledger.js +4 -4
  47. package/dist/ticket-provenance-contracts.js +2 -8
  48. package/dist/ticket-provenance.js +25 -9
  49. package/package.json +1 -1
  50. package/scripts/build-package.mjs +2 -0
  51. package/src/acp-host/production-host.ts +1 -1
  52. package/src/acp-host/role-turn-host.ts +11 -4
  53. package/src/analyst-gate-cycles-read.ts +31 -88
  54. package/src/analyst-ledger.ts +36 -51
  55. package/src/analyst-metric-families/acceptance-success-rework.ts +24 -1
  56. package/src/analyst-metric-families/gate-cycles.ts +1 -1
  57. package/src/analyst-metric-families/round-timeline.ts +2 -5
  58. package/src/analyst-page.ts +3 -3
  59. package/src/archivist-record-entry.ts +6 -5
  60. package/src/archivist-record-pointer.ts +92 -42
  61. package/src/atomic-write.ts +3 -1
  62. package/src/auditor-dossier-tool.ts +14 -8
  63. package/src/auditor-soul.ts +5 -10
  64. package/src/book-topology-migration-placement.ts +16 -3
  65. package/src/book-topology-record-class-migrators.ts +4 -2
  66. package/src/book-topology-runs-migrator.ts +6 -3
  67. package/src/collector-config.ts +5 -3
  68. package/src/doctor-contracts.ts +1 -1
  69. package/src/doctor-evidence.ts +7 -3
  70. package/src/engine-detour-tool.ts +1 -1
  71. package/src/engine-detour-usage.ts +12 -25
  72. package/src/external-host-turn-loop.ts +25 -0
  73. package/src/factory-board.ts +16 -81
  74. package/src/headless-host/production-host.ts +1 -4
  75. package/src/headless-host/role-turn-host.ts +56 -21
  76. package/src/host-descriptions.ts +0 -6
  77. package/src/host-session-record.ts +224 -140
  78. package/src/ledger-session-read.ts +6 -0
  79. package/src/navigator-public-session.ts +13 -18
  80. package/src/navigator-work-context.ts +3 -1
  81. package/src/notary-role.ts +2 -1
  82. package/src/notary-source-run.ts +8 -18
  83. package/src/packaged-role-registry.ts +1 -65
  84. package/src/pi/adapter.ts +50 -7
  85. package/src/pi/durable-principal.ts +2 -4
  86. package/src/pi/role-turn-host.ts +85 -14
  87. package/src/public-cli/auto-resume.ts +7 -43
  88. package/src/public-cli/instruction-seat-run.ts +13 -6
  89. package/src/public-cli/invocation.ts +90 -144
  90. package/src/public-cli/post-admission.ts +111 -72
  91. package/src/public-cli/run-lifecycle.ts +47 -115
  92. package/src/public-cli/settlement.ts +221 -589
  93. package/src/public-cli/terminal.ts +1 -61
  94. package/src/role-envelope.ts +4 -2
  95. package/src/role-run-placement.ts +65 -17
  96. package/src/role-run-relocation.ts +110 -70
  97. package/src/role-runtime.ts +46 -69
  98. package/src/run-dossier-files.ts +33 -0
  99. package/src/run-dossier.ts +357 -0
  100. package/src/run-terminal-artifacts.ts +84 -240
  101. package/src/run-ticket-number.ts +82 -14
  102. package/src/session-assistant-usage.ts +8 -20
  103. package/src/session-identity.ts +52 -21
  104. package/src/sitian-appender.ts +33 -26
  105. package/src/sitian-facade.ts +22 -0
  106. package/src/sitian-reader.ts +62 -32
  107. package/src/submission-gate.ts +1 -1
  108. package/src/submission-ledger.ts +4 -4
  109. package/src/ticket-provenance-contracts.ts +3 -6
  110. package/src/ticket-provenance.ts +23 -11
  111. package/src/ticket-snapshot.ts +3 -2
  112. package/src/ticket-trajectory.ts +95 -109
@@ -13,10 +13,11 @@ import { CliUsageError } from "./cli-errors.js";
13
13
  import { projectPublicTurnAxes } from "./turn-request.js";
14
14
  import { bindAdmittedTicketNumber, buildInstructionTransportPrompt, freezeAttachmentsIntoRun, relocateAdmittedRunToTicket, } from "./invocation.js";
15
15
  import { readRecordedSubmissionRows } from "../submission-ledger.js";
16
- import { readDeclaredTicketNumber } from "../run-ticket-number.js";
16
+ import { parseTicketNumber, readDeclaredTicketNumber } from "../run-ticket-number.js";
17
17
  import { pathContainedIn } from "../activation-ledger-topology.js";
18
18
  import { pickEngineAxis } from "../package-resources/engine-material.js";
19
19
  import { readStoredHostSessionId } from "../session-identity.js";
20
+ import { reportRunRecord } from "../sitian-facade.js";
20
21
  import { createReceiptDeliveryPolicy, deliveryLimitFromConfig, } from "../receipt-delivery-policy.js";
21
22
  import { rewriteRunDirectoryPathValue } from "../role-run-relocation.js";
22
23
  import { isOfficerReviewSeat } from "../packaged-role-registry.js";
@@ -40,10 +41,9 @@ import { mintEngineDetourInvocationScope, withEngineDetourInvocationScope, } fro
40
41
  import { clearCurrentCourt, describeErrorIdentity, markRunRunning, readCurrentCourt, recordCurrentCourt, } from "./run-lifecycle.js";
41
42
  import { processCancelDiagnostic, processCancelSignalName, } from "./process-cancel.js";
42
43
  import { DEFAULT_ROLE_TURN_HOST } from "../host-descriptions.js";
43
- import { recordRunStart } from "../host-session-record.js";
44
44
  import { classifyPostAdmissionFailure, exitCodeForTerminalOutcome, explicitInternalKnownFailureClassificationInput, formatCliDiagnostic, formatErrorCauseDetail, ledgerReadScope, isLawfulTypedTerminalOutcome, presentStructuralRejection, settleFailureTerminalResult, settleHostEndedNoReceipt, noteSettlementFault, attachRecordedSubmissions, retainPackageFault, } from "./settlement.js";
45
45
  import {} from "./terminal.js";
46
- import { ensureRealArtifactsDirectory, persistReturnedRunState, presentTerminal, runWithAutoResumeLoop, TurnDispatchedFailure, } from "./auto-resume.js";
46
+ import { persistReturnedRunState, presentTerminal, runWithAutoResumeLoop, TurnDispatchedFailure, } from "./auto-resume.js";
47
47
  import { isRecord, errorText } from "../unknown-value.js";
48
48
  function projectRelocatedTurnIdentity(request, result, admitted, relocation) {
49
49
  const rewrite = (value) => rewriteRunDirectoryPathValue(value, relocation.oldRunDirectory, relocation.newRunDirectory);
@@ -87,7 +87,7 @@ async function settleProcessCancelAfterTurn(input) {
87
87
  ? { knownDiagnostic: processCancelDiagnostic(input.cancelName) }
88
88
  : { knownFailure: input.result.knownFailure }),
89
89
  cancelName: input.cancelName,
90
- }, input.invocationScopeId), input.adapters, input.env.principalAuthority, input.io, input.persistRunState, input.notePackageFault);
90
+ }, input.invocationScopeId), input.adapters, input.env.principalAuthority, input.io, input.persistRunState, input.notePackageFault, input.courtAttemptId);
91
91
  return {
92
92
  ...failed,
93
93
  turnDispatched: true,
@@ -170,7 +170,9 @@ export async function resolveResumeMethodMaterialAdapters(input) {
170
170
  return { kind: "terminal", ...terminal };
171
171
  }
172
172
  }
173
- export async function presentControlledFailure(admitted, failureInput, adapters, authority, io, persistRunState = true, notePackageFault) {
173
+ export async function presentControlledFailure(admitted, failureInput, adapters, authority, io, persistRunState = true, notePackageFault,
174
+ /** Open-court identity already on the turn request / currentCourt (#1161). */
175
+ courtAttemptId) {
174
176
  const hasThrown = Object.hasOwn(failureInput, "thrown");
175
177
  const knownFailure = failureInput.knownFailure;
176
178
  // knownFailure channel owns details when present; otherwise caller knownDetails.
@@ -231,6 +233,9 @@ export async function presentControlledFailure(admitted, failureInput, adapters,
231
233
  const settled = await settleFailureTerminalResult(admitted, failure, authority, {
232
234
  recordAttemptHistory: true,
233
235
  ...(notePackageFault === undefined ? {} : { notePackageFault }),
236
+ ...(courtAttemptId === undefined || courtAttemptId.length === 0
237
+ ? {}
238
+ : { courtAttemptId }),
234
239
  ...(failureInput.invocationScopeId === undefined ||
235
240
  failureInput.invocationScopeId.length === 0
236
241
  ? {}
@@ -263,9 +268,9 @@ export async function presentControlledFailure(admitted, failureInput, adapters,
263
268
  * the true cause through its own existing dispatch-exception machinery once
264
269
  * the retry budget is exhausted.
265
270
  */
266
- async function settleAfterTurnStarted(admitted, failureInput, adapters, authority, io, persistRunState, notePackageFault) {
271
+ async function settleAfterTurnStarted(admitted, failureInput, adapters, authority, io, persistRunState, notePackageFault, courtAttemptId) {
267
272
  try {
268
- return (await presentControlledFailure(admitted, failureInput, adapters, authority, io, persistRunState, notePackageFault));
273
+ return (await presentControlledFailure(admitted, failureInput, adapters, authority, io, persistRunState, notePackageFault, courtAttemptId));
269
274
  }
270
275
  catch (error) {
271
276
  throw new TurnDispatchedFailure(error);
@@ -321,9 +326,9 @@ function settlementScopeForTurn(request) {
321
326
  *
322
327
  * The caller owns the live delivery policy; the request projects its next send.
323
328
  */
324
- async function buildReceiptDeliveryRequest(input) {
325
- const { admitted, env, request, receiptDelivery } = input;
326
- const hostSessionId = await readStoredHostSessionId(env.host, env.principalAuthority, admitted.principal);
329
+ /** Bare in-call催交 resume: hostSessionId absent; adapter is the sole load authority. */
330
+ function buildReceiptDeliveryRequest(input) {
331
+ const { request, receiptDelivery } = input;
327
332
  return {
328
333
  ...request,
329
334
  continuation: {
@@ -332,7 +337,6 @@ async function buildReceiptDeliveryRequest(input) {
332
337
  ...receiptDelivery.deliveryState(),
333
338
  deliveryTurns: receiptDelivery.issuedDeliveryRequests() + 1,
334
339
  }),
335
- ...(hostSessionId === undefined ? {} : { hostSessionId }),
336
340
  },
337
341
  deliveryRequestLimit: receiptDelivery.limit,
338
342
  };
@@ -378,19 +382,19 @@ async function settleCompletedHostTurn(input) {
378
382
  // machinery once the retry budget is exhausted.
379
383
  let stderrLogWriteFailure;
380
384
  try {
381
- await writeFile(join(admitted.runDirectory, "stderr.log"), result.stderr, "utf8");
385
+ reportRunRecord(admitted.runDirectory, "stderr", { text: result.stderr }, "post-admission");
382
386
  }
383
387
  catch (error) {
384
388
  stderrLogWriteFailure = error;
385
- // Best-effort: stderr.log is secondary to the host terminal. A write
389
+ // Best-effort: the stderr log line is secondary to the host terminal. A write
386
390
  // failure leaves a durable note and, on a host failure, rides in
387
391
  // packageFact. It does not become the cause.
388
- await recordBestEffortPostDispatchDiagnostic(admitted, env, `stderr.log write failed (best-effort continue): ${describeErrorIdentity(error)}`, io);
392
+ await recordBestEffortPostDispatchDiagnostic(admitted, env, `stderr log write failed (best-effort continue): ${describeErrorIdentity(error)}`, io);
389
393
  }
390
394
  // Host facts are resolved before trySettle. A host failure skips trySettle
391
395
  // so a later read cannot replace that report. A clean host whose settlement
392
396
  // read throws is noted above and is not turned into a failure terminal.
393
- // stderr.log and run-state writes are notes beside the host terminal.
397
+ // the stderr log line and run-state writes are notes beside the host terminal.
394
398
  let settled;
395
399
  let settledOutcome;
396
400
  // The host CLI's own report: timeout, declared failure, cancel, or exit.
@@ -440,6 +444,9 @@ async function settleCompletedHostTurn(input) {
440
444
  deferredPersist,
441
445
  invocationScopeId: request.invocationScopeId,
442
446
  notePackageFault: courtScope.notePackageFault,
447
+ ...(courtScope.courtAttemptId === undefined
448
+ ? {}
449
+ : { courtAttemptId: courtScope.courtAttemptId }),
443
450
  })) };
444
451
  }
445
452
  if (persistRunState) {
@@ -476,11 +483,62 @@ async function settleCompletedHostTurn(input) {
476
483
  // Secondary fact only — never the cause, and never merged into the
477
484
  // host's own details.
478
485
  ...(stderrLogWriteFact === undefined ? {} : { packageFact: stderrLogWriteFact }),
479
- }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState, courtScope.notePackageFault);
486
+ }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState, courtScope.notePackageFault, courtScope.courtAttemptId);
480
487
  return { kind: "settled", outcome: await finishAfterTurn(withProcessCancelSkipAutoResume({ ...failed, turnDispatched: true, ...deferredPersist }, env.signal)) };
481
488
  }
482
489
  return { kind: "still-missing" };
483
490
  }
491
+ /**
492
+ * #858 / #1071: the first identifiable ticketNumber field declaration among the
493
+ * run's sealed rows files an unbound run (integer, digit string, or leading #N
494
+ * token). Terminal rows match settlement (#881): accepted and audit-escalation —
495
+ * an escalated submission still carries the original role params. Later
496
+ * receipts remain untouched; prose note/report is never consulted; this seam
497
+ * does not adjudicate a ticket change. Runs in the public call's own process
498
+ * (no role leg writes the run's current.json).
499
+ */
500
+ export async function bindSealedTicketNumber(admitted) {
501
+ if (admitted.ticketNumber !== undefined)
502
+ return;
503
+ const rows = await readRecordedSubmissionRows(admitted.projectRoot, admitted.runId, ledgerReadScope(admitted));
504
+ let ticketNumber;
505
+ for (const row of rows) {
506
+ if (row.role !== admitted.role
507
+ || (row.kind !== "accepted" && row.kind !== "audit-escalation")) {
508
+ continue;
509
+ }
510
+ const payload = row.accepted;
511
+ if (!isRecord(payload))
512
+ continue;
513
+ ticketNumber = readDeclaredTicketNumber(payload.ticketNumber);
514
+ if (ticketNumber !== undefined)
515
+ break;
516
+ }
517
+ if (ticketNumber !== undefined)
518
+ await bindAdmittedTicketNumber(admitted, ticketNumber);
519
+ }
520
+ /**
521
+ * The ticket a diarist asserted on a completed submission, whether or not the
522
+ * rest of that submission was later accepted (a bounds reask does not unsay the
523
+ * ticket). Before this ran in the leg's accept hook; the leg now only appends its
524
+ * ledger rows and the public call's own process binds the ticket from them.
525
+ */
526
+ export async function bindDiaristAssertedTicketNumber(admitted) {
527
+ if (admitted.ticketNumber !== undefined)
528
+ return;
529
+ const rows = await readRecordedSubmissionRows(admitted.projectRoot, admitted.runId, ledgerReadScope(admitted));
530
+ for (const row of rows) {
531
+ if (row.role !== admitted.role || !isRecord(row.accepted))
532
+ continue;
533
+ if (row.accepted.status !== "completed" || !("ticketNumber" in row.accepted))
534
+ continue;
535
+ const ticketNumber = parseTicketNumber(row.accepted.ticketNumber);
536
+ if (ticketNumber !== undefined) {
537
+ await bindAdmittedTicketNumber(admitted, ticketNumber);
538
+ return;
539
+ }
540
+ }
541
+ }
484
542
  export async function dispatchPostAdmissionTurn(input) {
485
543
  const { admitted, env, io, request, lease, adapters, effectiveEngine } = input;
486
544
  const persistRunState = input.persistRunState !== false;
@@ -533,7 +591,7 @@ export async function dispatchPostAdmissionTurn(input) {
533
591
  knownDiagnostic: processCancelDiagnostic(cancelBeforeFinish),
534
592
  cancelName: cancelBeforeFinish,
535
593
  skipRunStateWrite: true,
536
- }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState, courtScope.notePackageFault)),
594
+ }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState, courtScope.notePackageFault, courtScope.courtAttemptId)),
537
595
  turnDispatched: true,
538
596
  skipAutoResume: true,
539
597
  ...deferredPersist,
@@ -575,24 +633,7 @@ export async function dispatchPostAdmissionTurn(input) {
575
633
  // an escalated submission still carries the original role params.
576
634
  // Later receipts remain untouched; prose note/report is never consulted;
577
635
  // this seam does not adjudicate a ticket change.
578
- if (admitted.ticketNumber === undefined) {
579
- const rows = await readRecordedSubmissionRows(admitted.projectRoot, admitted.runId, ledgerReadScope(admitted));
580
- let ticketNumber;
581
- for (const row of rows) {
582
- if (row.role !== admitted.role
583
- || (row.kind !== "accepted" && row.kind !== "audit-escalation")) {
584
- continue;
585
- }
586
- const payload = row.accepted;
587
- if (!isRecord(payload))
588
- continue;
589
- ticketNumber = readDeclaredTicketNumber(payload.ticketNumber);
590
- if (ticketNumber !== undefined)
591
- break;
592
- }
593
- if (ticketNumber !== undefined)
594
- await bindAdmittedTicketNumber(admitted, ticketNumber);
595
- }
636
+ await bindSealedTicketNumber(admitted);
596
637
  // #863: shared post-admission bind must relocate unbound→ticket in-home
597
638
  // before lease release (work-seat self-report and any prior board bind).
598
639
  const relocation = await relocateAdmittedRunToTicket(admitted, env.principalAuthority, lease);
@@ -618,7 +659,7 @@ export async function dispatchPostAdmissionTurn(input) {
618
659
  code: null,
619
660
  stderr: "",
620
661
  thrown: error,
621
- }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState, courtScope.notePackageFault)),
662
+ }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState, courtScope.notePackageFault, courtScope.courtAttemptId)),
622
663
  ...(result.turnDispatched === true ? { turnDispatched: true } : {}),
623
664
  ...(result.skipAutoResume === true ? { skipAutoResume: true } : {}),
624
665
  ...deferredPersist,
@@ -649,7 +690,7 @@ export async function dispatchPostAdmissionTurn(input) {
649
690
  code: null,
650
691
  stderr: "",
651
692
  thrown: error,
652
- }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState, courtScope.notePackageFault));
693
+ }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState, courtScope.notePackageFault, courtScope.courtAttemptId));
653
694
  return { ...settled, ...deferredPersist };
654
695
  }
655
696
  }
@@ -668,7 +709,7 @@ export async function dispatchPostAdmissionTurn(input) {
668
709
  turnRequest = { ...turnRequest, stationChild: env.stationChild };
669
710
  }
670
711
  // Selected host axis rides the shared Host envelope for in-turn tools
671
- // (detour usage ledger) — never a pre-spawn invocation.json reread.
712
+ // (detour usage ledger) — never a pre-spawn current.json reread.
672
713
  if (typeof env.host === "string" && env.host.trim() !== "") {
673
714
  turnRequest = { ...turnRequest, host: env.host.trim() };
674
715
  }
@@ -685,7 +726,6 @@ export async function dispatchPostAdmissionTurn(input) {
685
726
  // host CLI's native resume. Nothing here may gate, redirect or reshape
686
727
  // that dispatch on prior conclusions, row counts or report presence;
687
728
  // the authoritative post-turn settlement reads whatever really happened.
688
- recordRunStart(admitted.runDirectory);
689
729
  turnDispatched = true;
690
730
  result = await env.roleTurnHost.executeTurn(turnRequest);
691
731
  }
@@ -699,7 +739,7 @@ export async function dispatchPostAdmissionTurn(input) {
699
739
  // call is a second fact; it must not become a new Error in its place.
700
740
  ...(processCancelName === undefined ? {} : { cancelName: processCancelName }),
701
741
  thrown: error,
702
- }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState, courtScope.notePackageFault);
742
+ }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState, courtScope.notePackageFault, courtScope.courtAttemptId);
703
743
  return await finishAfterTurn(withProcessCancelSkipAutoResume({ ...settled, turnDispatched: true, ...deferredPersist }, env.signal));
704
744
  }
705
745
  // #1132: settle this turn through the ONE post-turn settlement authority,
@@ -734,11 +774,9 @@ export async function dispatchPostAdmissionTurn(input) {
734
774
  let deliveryResult;
735
775
  let deliveryTurnRequest;
736
776
  try {
737
- const deliveryRequest = await buildReceiptDeliveryRequest({
738
- admitted,
739
- env,
740
- // Host and the other axes already selected on this turn ride the
741
- // shared projection. The pre-projection request does not have them.
777
+ // Host and the other axes already selected on this turn ride the
778
+ // shared projection. The pre-projection request does not have them.
779
+ const deliveryRequest = buildReceiptDeliveryRequest({
742
780
  request: turnRequest,
743
781
  receiptDelivery,
744
782
  });
@@ -758,7 +796,7 @@ export async function dispatchPostAdmissionTurn(input) {
758
796
  // its true cause, through the one settlement authority (ADR 0080).
759
797
  // The turn started, so the caller's loop resumes instead of replaying
760
798
  // the initial payload. The issued count survives that re-entry.
761
- const settled = await settleAfterTurnStarted(admitted, withEngineDetourInvocationScope({ timedOut: false, code: null, stderr: "", thrown: error }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState);
799
+ const settled = await settleAfterTurnStarted(admitted, withEngineDetourInvocationScope({ timedOut: false, code: null, stderr: "", thrown: error }, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState, courtScope.notePackageFault, courtScope.courtAttemptId);
762
800
  return await finishAfterTurn(withProcessCancelSkipAutoResume({
763
801
  ...settled,
764
802
  turnDispatched: true,
@@ -818,6 +856,9 @@ export async function dispatchPostAdmissionTurn(input) {
818
856
  deferredPersist,
819
857
  invocationScopeId: request.invocationScopeId,
820
858
  notePackageFault: courtScope.notePackageFault,
859
+ ...(courtScope.courtAttemptId === undefined
860
+ ? {}
861
+ : { courtAttemptId: courtScope.courtAttemptId }),
821
862
  }));
822
863
  }
823
864
  if (persistRunState) {
@@ -1111,6 +1152,9 @@ export async function runPostAdmissionSeatResume(input) {
1111
1152
  };
1112
1153
  }
1113
1154
  }
1155
+ // Public explicit resume: attach the stored native id when the caller
1156
+ // left it unset (399c3c8c). In-call auto-resume / 催交 / gate retry omit
1157
+ // the field; those load inside the host adapter (host-contracts).
1114
1158
  let turnRequest = await input.buildTurnRequest(admittedForBuild, request);
1115
1159
  if (turnRequest.continuation.kind === "resume"
1116
1160
  && turnRequest.continuation.hostSessionId === undefined) {
@@ -1211,7 +1255,7 @@ export async function runPostAdmissionSeatResume(input) {
1211
1255
  catch (error) {
1212
1256
  if (error instanceof TurnDispatchedFailure)
1213
1257
  throw error;
1214
- await presentResumeFailurePointer(input.io, error, (failure) => writeResumeDiagnosticFile(loaded.admitted.runDirectory, loaded.admitted.runId, failure, loaded.admitted.role));
1258
+ await presentResumeFailurePointer(input.io, error, (failure) => writeResumeDiagnostic(loaded.admitted.runDirectory, loaded.admitted.runId, failure, loaded.admitted.role));
1215
1259
  return { exitCode: error instanceof CliUsageError ? 2 : 1 };
1216
1260
  }
1217
1261
  }
@@ -1231,12 +1275,12 @@ async function pointExistingRunFailure(home, runId, authority, io, thrown) {
1231
1275
  record = await readRoleRunState(runDirectory, authority);
1232
1276
  }
1233
1277
  catch {
1234
- await presentResumeFailurePointer(io, thrown, (failure) => writeResumeDiagnosticFile(runDirectory, runId, failure));
1278
+ await presentResumeFailurePointer(io, thrown, (failure) => writeResumeDiagnostic(runDirectory, runId, failure));
1235
1279
  return true;
1236
1280
  }
1237
1281
  if (record === undefined)
1238
1282
  return false;
1239
- await presentResumeFailurePointer(io, thrown, (failure) => writeResumeDiagnosticFile(runDirectory, runId, failure, record.role));
1283
+ await presentResumeFailurePointer(io, thrown, (failure) => writeResumeDiagnostic(runDirectory, runId, failure, record.role));
1240
1284
  return true;
1241
1285
  }
1242
1286
  export async function presentLocatedResumeFailure(home, runId, authority, io, thrown) {
@@ -1275,18 +1319,15 @@ async function presentResumeFailurePointer(io, thrown, publish) {
1275
1319
  }, io);
1276
1320
  }
1277
1321
  }
1278
- async function writeResumeDiagnosticFile(runDirectory, runId, failure, role) {
1279
- const dir = await ensureRealArtifactsDirectory(runDirectory);
1280
- const path = join(dir, `resume-diagnostic-${randomUUID()}.json`);
1281
- await writeFile(path, `${JSON.stringify({
1322
+ async function writeResumeDiagnostic(runDirectory, runId, failure, role) {
1323
+ return reportRunRecord(runDirectory, "resume-diagnostic", {
1282
1324
  runId,
1283
1325
  ...(role === undefined ? {} : { role }),
1284
1326
  diagnostic: failure.diagnostic,
1285
1327
  ...(failure.cause === undefined ? {} : { cause: failure.cause }),
1286
1328
  ...(failure.identity === undefined ? {} : { identity: failure.identity }),
1287
1329
  ...(failure.details === undefined ? {} : { details: failure.details }),
1288
- }, null, 2)}\n`, { encoding: "utf8", flag: "wx" });
1289
- return path;
1330
+ }, "post-admission").recordFile;
1290
1331
  }
1291
1332
  /**
1292
1333
  * Shared post-admission one-shot path: folds into runPostAdmissionResumable (#840 / #416).