@akagilnc/pi-workflow-roles 0.1.5382 → 0.1.5462
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/README.zh-CN.md +4 -2
- package/dist/acp-host/production-host.js +8843 -9012
- package/dist/archivist-record-pointer.js +38 -0
- package/dist/compliance-transport.js +7 -5
- package/dist/doctor-auditor.js +1 -0
- package/dist/engine-detour-usage.js +9 -36
- package/dist/gatekeeper-role.js +4 -18
- package/dist/headless-host/description.js +0 -209
- package/dist/headless-host/production-host.js +7828 -8247
- package/dist/host-contracts.js +8 -0
- package/dist/judge-role.js +14 -1
- package/dist/migrate-book-topology.js +215 -96
- package/dist/navigator-attendance.js +10 -9
- package/dist/navigator-invocation-identity.js +18 -0
- package/dist/packaged-role-registry.js +1 -9
- package/dist/pi/role-turn-host.js +46 -19
- package/dist/public-cli/auto-resume.js +29 -66
- package/dist/public-cli/cli.js +1 -0
- package/dist/public-cli/countersign-run.js +4 -18
- package/dist/public-cli/instruction-seat-run.js +258 -69
- package/dist/public-cli/main.js +7488 -7758
- package/dist/public-cli/post-admission.js +451 -349
- package/dist/public-cli/process-cancel.js +8 -0
- package/dist/public-cli/run-lifecycle.js +24 -94
- package/dist/public-cli/settlement.js +624 -1471
- package/dist/public-cli/terminal.js +34 -53
- package/dist/public-cli/turn-request.js +3 -0
- package/dist/public-role-summons.js +3 -8
- package/dist/receipt-delivery-policy.js +162 -28
- package/dist/run-terminal-artifacts.js +19 -14
- package/dist/serialize-thrown-value.js +7 -1
- package/dist/submission-errors.js +11 -1
- package/dist/submission-gate.js +27 -4
- package/dist/submission-ledger.js +21 -89
- package/package.json +1 -1
- package/scripts/build-package.mjs +0 -2
- package/src/acp-host/role-turn-host.ts +168 -75
- package/src/archivist-record-pointer.ts +48 -0
- package/src/compliance-transport.ts +13 -8
- package/src/doctor-auditor.ts +3 -0
- package/src/engine-detour-usage.ts +10 -39
- package/src/external-host-turn-loop.ts +100 -43
- package/src/gatekeeper-role.ts +7 -22
- package/src/headless-host/description.ts +4 -214
- package/src/headless-host/production-host.ts +2 -1
- package/src/headless-host/role-turn-host.ts +153 -186
- package/src/host-contracts.ts +20 -10
- package/src/judge-role.ts +24 -5
- package/src/navigator-attendance.ts +17 -12
- package/src/navigator-invocation-identity.ts +31 -0
- package/src/navigator-public-session.ts +1 -1
- package/src/navigator-session-contracts.ts +1 -1
- package/src/packaged-role-registry.ts +2 -10
- package/src/pi/adapter.ts +33 -11
- package/src/pi/role-turn-host.ts +49 -28
- package/src/prepared-role-turn.ts +2 -0
- package/src/public-cli/auto-resume.ts +27 -66
- package/src/public-cli/cli.ts +1 -0
- package/src/public-cli/countersign-run.ts +4 -22
- package/src/public-cli/instruction-seat-run.ts +307 -74
- package/src/public-cli/post-admission.ts +615 -459
- package/src/public-cli/process-cancel.ts +9 -0
- package/src/public-cli/run-lifecycle.ts +25 -126
- package/src/public-cli/settlement.ts +801 -1859
- package/src/public-cli/terminal.ts +42 -70
- package/src/public-cli/turn-request.ts +10 -1
- package/src/public-role-summons.ts +3 -8
- package/src/receipt-delivery-policy.ts +219 -28
- package/src/role-envelope.ts +21 -10
- package/src/role-runtime-dependencies.ts +1 -0
- package/src/role-runtime.ts +79 -102
- package/src/run-terminal-artifacts.ts +21 -17
- package/src/serialize-thrown-value.ts +7 -1
- package/src/submission-correctable-error.ts +5 -2
- package/src/submission-errors.ts +12 -1
- package/src/submission-gate.ts +34 -4
- package/src/submission-ledger.ts +30 -116
- package/src/worker-role.ts +19 -7
- package/src/worker-submission-gates.ts +29 -7
- package/dist/audit-escalation.js +0 -7
- package/dist/pi/known-failure.js +0 -51
- package/dist/typed-provider-http.js +0 -57
- package/dist/upstream-error-testimony.js +0 -19
- package/src/pi/known-failure.ts +0 -76
- package/src/typed-provider-http.ts +0 -89
- package/src/upstream-error-testimony.ts +0 -45
|
@@ -6,17 +6,18 @@
|
|
|
6
6
|
import { dirname, resolve } from "node:path";
|
|
7
7
|
import { isUnboundRunDirectory } from "../role-run-placement.ts";
|
|
8
8
|
import { AUDITOR_DOSSIER_PROMPT } from "../compliance-transport.ts";
|
|
9
|
-
import { bookDirectOfficerRunPointer } from "../archivist-record-pointer.ts";
|
|
9
|
+
import { bookDirectOfficerRunPointer, readDirectOfficerRunPointer } from "../archivist-record-pointer.ts";
|
|
10
10
|
import { createPiDoctorAuditor } from "../doctor-auditor.ts";
|
|
11
11
|
|
|
12
12
|
import type { DurablePrincipalAuthority, HostContext, RoleTurnRequest } from "../host-contracts.ts";
|
|
13
|
-
import { officerConclusionReask, gateOfficerForSubject } from "../gatekeeper-role.ts";
|
|
13
|
+
import { officerConclusionReask, gateOfficerForSubject, type GateOfficer } from "../gatekeeper-role.ts";
|
|
14
14
|
import { receivedDiscriminator } from "../submission-errors.ts";
|
|
15
15
|
import { REVIEW_QUEUE_STATUSES } from "../review-submission.ts";
|
|
16
16
|
import { runJudgeGates } from "../judge-role.ts";
|
|
17
17
|
import { WORKER_DONE_STATUSES } from "../worker-submission-contracts.ts";
|
|
18
18
|
import { SECRETARIAT_GATE_OFFICER_ENTRY_TYPE } from "../secretariat-contracts.ts";
|
|
19
19
|
import { readableGateItem } from "../readable-gate-item.ts";
|
|
20
|
+
import { deliveryLimitFromConfig } from "../receipt-delivery-policy.ts";
|
|
20
21
|
import { runIdFromRunDirectory } from "../run-terminal-artifacts.ts";
|
|
21
22
|
import { createDefaultGateOfficerSummon, requireSubmissionGate } from "../submission-gate.ts";
|
|
22
23
|
import { readRecordedSubmissionRows } from "../submission-ledger.ts";
|
|
@@ -56,6 +57,7 @@ import {
|
|
|
56
57
|
} from "./invocation.ts";
|
|
57
58
|
import {
|
|
58
59
|
presentControlledFailure,
|
|
60
|
+
packageFaultNoteFor,
|
|
59
61
|
prepareSummonsResumeMaterials,
|
|
60
62
|
roleTurnOptions,
|
|
61
63
|
runPostAdmissionOneShot,
|
|
@@ -66,11 +68,13 @@ import {
|
|
|
66
68
|
type PostAdmissionAdapters,
|
|
67
69
|
type PostAdmissionEnv,
|
|
68
70
|
} from "./post-admission.ts";
|
|
71
|
+
import { presentTerminal } from "./auto-resume.ts";
|
|
69
72
|
import {
|
|
70
73
|
buildAutoResumeContinuationPrompt,
|
|
71
74
|
loadResumablePublicRole,
|
|
72
75
|
markRunAdmitted,
|
|
73
76
|
parentRunPathFromGatePointerInstruction,
|
|
77
|
+
readCurrentCourt,
|
|
74
78
|
type PublicResumeRequest,
|
|
75
79
|
type RunWriterLease,
|
|
76
80
|
type SameTicketSummonsMaterials,
|
|
@@ -79,9 +83,9 @@ import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.ts";
|
|
|
79
83
|
import {
|
|
80
84
|
presentStructuralRejection,
|
|
81
85
|
readBoundSessionEntries,
|
|
82
|
-
seatKnownFailureResolver,
|
|
83
86
|
attachPostAuditProjection,
|
|
84
87
|
trySettlePublicSeat,
|
|
88
|
+
type SettlementCourtScope,
|
|
85
89
|
} from "./settlement.ts";
|
|
86
90
|
import type { CliIo } from "./cli-io.ts";
|
|
87
91
|
import { warnMissingMethodSkills } from "./machine-method-skills.ts";
|
|
@@ -89,11 +93,9 @@ import {
|
|
|
89
93
|
formatTerminalResult,
|
|
90
94
|
isLawfulTypedTerminalOutcome,
|
|
91
95
|
type TerminalResult,
|
|
92
|
-
type TerminalRoleName,
|
|
93
96
|
} from "./terminal.ts";
|
|
94
97
|
import {
|
|
95
98
|
admittedSeatTurnDetails,
|
|
96
|
-
projectPublicTurnAxes,
|
|
97
99
|
projectRoleTurnRequest,
|
|
98
100
|
requiredMethodSkills,
|
|
99
101
|
type RoleTurnRequestProjectionOptions,
|
|
@@ -167,17 +169,105 @@ function unreadablePostSubmissionStatus(
|
|
|
167
169
|
: route.reask ?? officerConclusionReask(status);
|
|
168
170
|
}
|
|
169
171
|
|
|
172
|
+
/**
|
|
173
|
+
* One more unreadable-status reask. This loop has its own counter and reads
|
|
174
|
+
* the same autoResumeLimit as the other loops. Exhaustion is not a readable
|
|
175
|
+
* status: the caller presents the volumes already in hand and does not advance
|
|
176
|
+
* review. ADR 0007 audit continues are not this shape.
|
|
177
|
+
*/
|
|
178
|
+
function withUnreadableReask(env: InstructionSeatRunEnv): InstructionSeatRunEnv | undefined {
|
|
179
|
+
const spent = env.unreadableReasksSpent ?? 0;
|
|
180
|
+
if (spent >= deliveryLimitFromConfig(env.autoResumeLimit)) return undefined;
|
|
181
|
+
return { ...env, unreadableReasksSpent: spent + 1 };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Budget spent on an unreadable status. Distinct from "status is readable". */
|
|
185
|
+
const UNREADABLE_REASK_EXHAUSTED = { unreadableReaskExhausted: true as const };
|
|
186
|
+
|
|
187
|
+
function isUnreadableReaskExhausted(
|
|
188
|
+
value: SeatRunResult | typeof UNREADABLE_REASK_EXHAUSTED | undefined,
|
|
189
|
+
): value is typeof UNREADABLE_REASK_EXHAUSTED {
|
|
190
|
+
return value === UNREADABLE_REASK_EXHAUSTED;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function presentOriginalVolume(
|
|
194
|
+
held: readonly string[],
|
|
195
|
+
terminal: TerminalResult | undefined,
|
|
196
|
+
io: CliIo,
|
|
197
|
+
runDirectory?: string,
|
|
198
|
+
): Promise<void> {
|
|
199
|
+
if (terminal !== undefined && runDirectory !== undefined) {
|
|
200
|
+
// Direction facts were attached after the held volume was formatted.
|
|
201
|
+
await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, runDirectory,
|
|
202
|
+
terminal.roleOutcome.decisiveFacts?.directionUnsettled === true ? undefined : held);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
// No settled host report exists to preserve at this pre-result boundary.
|
|
206
|
+
for (const value of held) io.stdout(value);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** Runtime fact beside the original volume. Payloads stay as submitted. */
|
|
210
|
+
function withUnsettledDirection(
|
|
211
|
+
parent: TerminalResult,
|
|
212
|
+
officer?: TerminalResult,
|
|
213
|
+
): TerminalResult {
|
|
214
|
+
const outcome = parent.roleOutcome;
|
|
215
|
+
if (outcome.kind !== "accepted" && outcome.kind !== "audit_escalation") return parent;
|
|
216
|
+
const officerOutcome = officer?.roleOutcome;
|
|
217
|
+
const officerPayloads = officer?.submissions !== undefined && officer.submissions.length > 0
|
|
218
|
+
? officer.submissions
|
|
219
|
+
: officerOutcome !== undefined && officerOutcome.kind !== "no_receipt"
|
|
220
|
+
? officerOutcome.payloads ?? []
|
|
221
|
+
: [];
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
...parent,
|
|
225
|
+
roleOutcome: {
|
|
226
|
+
...outcome,
|
|
227
|
+
decisiveFacts: {
|
|
228
|
+
...(outcome.decisiveFacts ?? {}),
|
|
229
|
+
directionUnsettled: true,
|
|
230
|
+
subsequentAudit: "incomplete",
|
|
231
|
+
...(officerOutcome === undefined ? {} : { officerRole: officerOutcome.role }),
|
|
232
|
+
...(officer?.runId === undefined ? {} : { officerRunId: officer.runId }),
|
|
233
|
+
...(officerPayloads.length === 0 ? {} : { officerPayloads }),
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function heldUnreadableTerminal(terminal: TerminalResult | undefined): boolean {
|
|
240
|
+
if (terminal?.roleOutcome.kind !== "accepted") return false;
|
|
241
|
+
if (latestPayloadEscalated(terminal.roleOutcome)) return false;
|
|
242
|
+
const status = latestQueueStatus(terminal);
|
|
243
|
+
return typeof status !== "string" || !REVIEW_QUEUE_STATUSES.has(status);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function presentUnsettledAudit(
|
|
247
|
+
parent: TerminalResult,
|
|
248
|
+
officer: TerminalResult | undefined,
|
|
249
|
+
io: CliIo,
|
|
250
|
+
runDirectory: string,
|
|
251
|
+
): Promise<TerminalResult> {
|
|
252
|
+
const terminal = withUnsettledDirection(parent, officer);
|
|
253
|
+
await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, runDirectory);
|
|
254
|
+
if (officer !== undefined) await presentTerminal(officer, { ...io, omitFailureStderrDiagnostic: true }, runDirectory);
|
|
255
|
+
return terminal;
|
|
256
|
+
}
|
|
257
|
+
|
|
170
258
|
async function reaskUnreadablePostSubmissionStatus(
|
|
171
259
|
admitted: AdmittedRoleInvocation,
|
|
172
260
|
terminal: TerminalResult | undefined,
|
|
173
261
|
env: InstructionSeatRunEnv,
|
|
174
262
|
io: CliIo,
|
|
175
|
-
|
|
176
|
-
|
|
263
|
+
message = unreadablePostSubmissionStatus(admitted, terminal),
|
|
264
|
+
): Promise<SeatRunResult | typeof UNREADABLE_REASK_EXHAUSTED | undefined> {
|
|
177
265
|
if (message === undefined) return undefined;
|
|
266
|
+
const next = withUnreadableReask(env);
|
|
267
|
+
if (next === undefined) return UNREADABLE_REASK_EXHAUSTED;
|
|
178
268
|
return runPublicInstructionSeatResume(
|
|
179
|
-
{ runId: admitted.runId, message },
|
|
180
|
-
|
|
269
|
+
{ runId: admitted.runId, summons: { instruction: message } },
|
|
270
|
+
next,
|
|
181
271
|
io,
|
|
182
272
|
);
|
|
183
273
|
}
|
|
@@ -220,11 +310,6 @@ function initialPrompt(
|
|
|
220
310
|
);
|
|
221
311
|
}
|
|
222
312
|
|
|
223
|
-
function infraFailure(role: PackagedRole) {
|
|
224
|
-
const resolveRunnerKnownFailure = seatKnownFailureResolver(role);
|
|
225
|
-
return resolveRunnerKnownFailure === undefined ? {} : { resolveRunnerKnownFailure };
|
|
226
|
-
}
|
|
227
|
-
|
|
228
313
|
function isBoardTicketSeat(
|
|
229
314
|
seat: AdmittedRoleInvocation,
|
|
230
315
|
): seat is AdmittedRoleInvocation & { role: "diarist" } {
|
|
@@ -244,6 +329,14 @@ async function bindAndRelocateDiarist(
|
|
|
244
329
|
return await relocateAdmittedRunToTicket(admitted, authority, lease);
|
|
245
330
|
}
|
|
246
331
|
|
|
332
|
+
function packageFaultScope(
|
|
333
|
+
admitted: Pick<AdmittedRoleInvocation, "runDirectory" | "principal">,
|
|
334
|
+
env: InstructionSeatRunEnv,
|
|
335
|
+
io: CliIo,
|
|
336
|
+
): SettlementCourtScope {
|
|
337
|
+
return { notePackageFault: packageFaultNoteFor(admitted, env, io) };
|
|
338
|
+
}
|
|
339
|
+
|
|
247
340
|
function seatAdapters(
|
|
248
341
|
admitted: AdmittedRoleInvocation,
|
|
249
342
|
env: InstructionSeatRunEnv,
|
|
@@ -257,7 +350,6 @@ function seatAdapters(
|
|
|
257
350
|
...(present === "typed"
|
|
258
351
|
? { shouldPresentSettled: (terminal: TerminalResult) => isLawfulTypedTerminalOutcome(terminal.roleOutcome) }
|
|
259
352
|
: {}),
|
|
260
|
-
...infraFailure(admitted.role),
|
|
261
353
|
...(packagedBindsBoardTicket(admitted.role)
|
|
262
354
|
? {
|
|
263
355
|
beforeDispatch: async (seat: AdmittedRoleInvocation, lease?: RunWriterLease) => {
|
|
@@ -373,11 +465,18 @@ async function dispatchAdmitted(
|
|
|
373
465
|
env,
|
|
374
466
|
io,
|
|
375
467
|
);
|
|
468
|
+
if (isUnreadableReaskExhausted(unreadableReask)) {
|
|
469
|
+
const terminal = result.terminal === undefined
|
|
470
|
+
? undefined
|
|
471
|
+
: withUnsettledDirection(result.terminal);
|
|
472
|
+
await presentOriginalVolume(held, terminal, io, admitted.runDirectory);
|
|
473
|
+
return terminal === undefined ? result : { ...result, terminal };
|
|
474
|
+
}
|
|
376
475
|
if (unreadableReask !== undefined) return unreadableReask;
|
|
377
476
|
if (AUDITED_ROLES.has(admitted.role) && result.terminal?.roleOutcome.kind === "accepted") {
|
|
378
477
|
return auditSubmittedRole(result, env, io);
|
|
379
478
|
}
|
|
380
|
-
|
|
479
|
+
await presentOriginalVolume(held, result.terminal, io, admitted.runDirectory);
|
|
381
480
|
return result;
|
|
382
481
|
}
|
|
383
482
|
|
|
@@ -454,7 +553,9 @@ async function runOmittedLensBatch(
|
|
|
454
553
|
},
|
|
455
554
|
artifacts: terminals.flatMap((item) => item.artifacts),
|
|
456
555
|
};
|
|
457
|
-
|
|
556
|
+
const childRunDirectory = children.completeness.admitted?.runDirectory ?? children.correctness.admitted?.runDirectory;
|
|
557
|
+
if (childRunDirectory !== undefined) await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, childRunDirectory);
|
|
558
|
+
else io.stdout(formatTerminalResult(terminal));
|
|
458
559
|
return { exitCode: failed ? 1 : 0, terminal };
|
|
459
560
|
}
|
|
460
561
|
|
|
@@ -559,23 +660,17 @@ async function runCountersignBody(
|
|
|
559
660
|
await persistAdmittedSourceRunPath(admitted, gateParentRunPath);
|
|
560
661
|
admitted = { ...admitted, sourceRunPath: gateParentRunPath };
|
|
561
662
|
}
|
|
562
|
-
const turnProjection
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
...pickEngineAxis(env),
|
|
574
|
-
packageRoot: env.packageRoot,
|
|
575
|
-
}),
|
|
576
|
-
),
|
|
577
|
-
},
|
|
578
|
-
};
|
|
663
|
+
const turnProjection = roleTurnOptions(env, admitted, {
|
|
664
|
+
kind: "initial",
|
|
665
|
+
prompt: (env.reviewReask ?? env.gateReviewInstruction)
|
|
666
|
+
?? buildInstructionTransportPrompt(
|
|
667
|
+
admitted,
|
|
668
|
+
engineSessionMaterialFromOptions({
|
|
669
|
+
...pickEngineAxis(env),
|
|
670
|
+
packageRoot: env.packageRoot,
|
|
671
|
+
}),
|
|
672
|
+
),
|
|
673
|
+
});
|
|
579
674
|
const turnRequest = buildInstructionSeatTurnRequest(admitted, turnProjection);
|
|
580
675
|
const result = await runPostAdmissionOneShot({
|
|
581
676
|
admitted,
|
|
@@ -624,7 +719,7 @@ export async function runPublicInstructionSeat(
|
|
|
624
719
|
stdout: (value) => held.push(value), stderr: io.stderr,
|
|
625
720
|
});
|
|
626
721
|
if (result.terminal?.roleOutcome.kind === "accepted") return auditSubmittedRole(result, env, io);
|
|
627
|
-
|
|
722
|
+
await presentOriginalVolume(held, result.terminal, io, result.admitted?.runDirectory);
|
|
628
723
|
return result;
|
|
629
724
|
}
|
|
630
725
|
|
|
@@ -789,7 +884,8 @@ export async function runPublicInstructionSeat(
|
|
|
789
884
|
} catch (error) {
|
|
790
885
|
return await presentControlledFailure(admitted, {
|
|
791
886
|
timedOut: false, code: null, stderr: "", thrown: error,
|
|
792
|
-
}, seatAdapters(admitted, env), env.principalAuthority, io
|
|
887
|
+
}, seatAdapters(admitted, env), env.principalAuthority, io, true,
|
|
888
|
+
packageFaultNoteFor(admitted, env, io)) as SeatRunResult;
|
|
793
889
|
}
|
|
794
890
|
if (outcome.admitted !== undefined && isUnboundRunDirectory(outcome.admitted.runDirectory)) {
|
|
795
891
|
await recordChildDiaristRun(admitted, outcome.admitted.runId);
|
|
@@ -798,12 +894,13 @@ export async function runPublicInstructionSeat(
|
|
|
798
894
|
return await presentControlledFailure(admitted, {
|
|
799
895
|
timedOut: false, code: null, stderr: "",
|
|
800
896
|
thrown: new Error(outcome.failedWithoutEscalate.diagnostic),
|
|
801
|
-
}, seatAdapters(admitted, env), env.principalAuthority, io
|
|
897
|
+
}, seatAdapters(admitted, env), env.principalAuthority, io, true,
|
|
898
|
+
packageFaultNoteFor(admitted, env, io)) as SeatRunResult;
|
|
802
899
|
}
|
|
803
900
|
// The diarist's escalation pauses only the diarist's own run; call order
|
|
804
901
|
// belongs to the caller, so the Secretariat still takes its own turn.
|
|
805
902
|
if (outcome.identity.kind === "escalate" && outcome.terminal !== undefined) {
|
|
806
|
-
|
|
903
|
+
await presentTerminal(outcome.terminal, { ...io, omitFailureStderrDiagnostic: true }, outcome.admitted?.runDirectory ?? admitted.runDirectory);
|
|
807
904
|
}
|
|
808
905
|
}
|
|
809
906
|
return dispatchAdmitted(admitted, env, io);
|
|
@@ -879,12 +976,19 @@ export async function runPublicInstructionSeatResume(
|
|
|
879
976
|
env,
|
|
880
977
|
io,
|
|
881
978
|
);
|
|
979
|
+
if (isUnreadableReaskExhausted(unreadableReask)) {
|
|
980
|
+
const terminal = result.terminal === undefined
|
|
981
|
+
? undefined
|
|
982
|
+
: withUnsettledDirection(result.terminal);
|
|
983
|
+
await presentOriginalVolume(held, terminal, io, result.admitted?.runDirectory);
|
|
984
|
+
return terminal === undefined ? result : { ...result, terminal };
|
|
985
|
+
}
|
|
882
986
|
if (unreadableReask !== undefined) return unreadableReask;
|
|
883
987
|
if (result.admitted !== undefined && AUDITED_ROLES.has(result.admitted.role)
|
|
884
988
|
&& result.terminal?.roleOutcome.kind === "accepted") {
|
|
885
989
|
return auditSubmittedRole(result, env, io);
|
|
886
990
|
}
|
|
887
|
-
|
|
991
|
+
await presentOriginalVolume(held, result.terminal, io, result.admitted?.runDirectory);
|
|
888
992
|
return result;
|
|
889
993
|
};
|
|
890
994
|
let binding: Awaited<ReturnType<typeof readAuditorResumeBinding>>;
|
|
@@ -910,7 +1014,11 @@ const GATE_CHILD_ROLES = new Set(["notary", "auditor", "inspector", "countersign
|
|
|
910
1014
|
|
|
911
1015
|
/**
|
|
912
1016
|
* A gate child's conclusion outside the three states goes back to that child.
|
|
913
|
-
* The words are the existing officer re-ask.
|
|
1017
|
+
* The words are the existing officer re-ask. Each reask spends this loop's own
|
|
1018
|
+
* copy of the configured ceiling; exhaustion keeps the terminal already in hand.
|
|
1019
|
+
* A host failure stops here.
|
|
1020
|
+
* Countersign already spends that ceiling inside its own seat, or the summoning
|
|
1021
|
+
* gate does. This loop does not open a second one for the same conclusion.
|
|
914
1022
|
*/
|
|
915
1023
|
async function queueConclusionFromChild(
|
|
916
1024
|
child: AdmittedRoleInvocation,
|
|
@@ -922,22 +1030,41 @@ async function queueConclusionFromChild(
|
|
|
922
1030
|
| undefined
|
|
923
1031
|
> {
|
|
924
1032
|
if (!GATE_CHILD_ROLES.has(child.role)) return undefined;
|
|
925
|
-
|
|
1033
|
+
if (child.role === "countersign") {
|
|
1034
|
+
const terminal = await trySettlePublicSeat(
|
|
1035
|
+
child, env.principalAuthority, { ...await readCurrentCourt(child.runDirectory), ...packageFaultScope(child, env, io) },
|
|
1036
|
+
);
|
|
1037
|
+
const status = latestQueueStatus(terminal);
|
|
1038
|
+
if (terminal !== undefined && typeof status === "string" && REVIEW_QUEUE_STATUSES.has(status)) {
|
|
1039
|
+
return { admitted: child, terminal, status };
|
|
1040
|
+
}
|
|
1041
|
+
return { stop: { exitCode: 0, ...(terminal === undefined ? {} : { terminal }) } };
|
|
1042
|
+
}
|
|
1043
|
+
let current: AdmittedRoleInvocation = child;
|
|
1044
|
+
// Notary, auditor, and inspector have no seat-local status reask. This loop
|
|
1045
|
+
// is their one budget. The child resume keeps the caller's env so delivery,
|
|
1046
|
+
// failure recovery, and other reask loops stay separate.
|
|
1047
|
+
let budgetEnv: InstructionSeatRunEnv = { ...env, unreadableReasksSpent: 0 };
|
|
926
1048
|
for (;;) {
|
|
927
1049
|
const terminal = await trySettlePublicSeat(
|
|
928
1050
|
current,
|
|
929
1051
|
env.principalAuthority,
|
|
930
|
-
|
|
1052
|
+
{ ...await readCurrentCourt(current.runDirectory), ...packageFaultScope(current, env, io) },
|
|
931
1053
|
);
|
|
932
1054
|
const status = latestQueueStatus(terminal);
|
|
933
1055
|
if (terminal !== undefined && typeof status === "string" && REVIEW_QUEUE_STATUSES.has(status)) {
|
|
934
1056
|
return { admitted: current, terminal, status };
|
|
935
1057
|
}
|
|
936
|
-
const reasked = await
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1058
|
+
const reasked = await reaskUnreadablePostSubmissionStatus(
|
|
1059
|
+
current, terminal, budgetEnv, io, officerConclusionReask(status),
|
|
1060
|
+
);
|
|
1061
|
+
if (reasked === undefined || isUnreadableReaskExhausted(reasked)) {
|
|
1062
|
+
return { stop: { exitCode: 0, ...(terminal === undefined ? {} : { terminal }) } };
|
|
1063
|
+
}
|
|
1064
|
+
budgetEnv = withUnreadableReask(budgetEnv)!;
|
|
1065
|
+
if (reasked.exitCode !== 0 || reasked.admitted === undefined || reasked.terminal === undefined
|
|
1066
|
+
|| reasked.terminal.roleOutcome.kind === "no_receipt"
|
|
1067
|
+
|| reasked.terminal.roleOutcome.decisiveFacts?.directionUnsettled === true) {
|
|
941
1068
|
return { stop: reasked };
|
|
942
1069
|
}
|
|
943
1070
|
const reaskedStatus = latestQueueStatus(reasked.terminal);
|
|
@@ -962,34 +1089,90 @@ export async function continueParentAfterChild(
|
|
|
962
1089
|
}
|
|
963
1090
|
const admitted = loaded.admitted;
|
|
964
1091
|
const resolved = await queueConclusionFromChild(child, env, io);
|
|
965
|
-
if (resolved !== undefined && "stop" in resolved)
|
|
1092
|
+
if (resolved !== undefined && "stop" in resolved) {
|
|
1093
|
+
const stopped = resolved.stop;
|
|
1094
|
+
if (
|
|
1095
|
+
stopped.exitCode === 0
|
|
1096
|
+
&& heldUnreadableTerminal(stopped.terminal)
|
|
1097
|
+
&& stopped.terminal !== undefined
|
|
1098
|
+
) {
|
|
1099
|
+
const parentTerminal = await trySettlePublicSeat(admitted, env.principalAuthority, undefined);
|
|
1100
|
+
if (
|
|
1101
|
+
parentTerminal?.roleOutcome.kind === "accepted"
|
|
1102
|
+
|| parentTerminal?.roleOutcome.kind === "audit_escalation"
|
|
1103
|
+
) {
|
|
1104
|
+
const terminal = await presentUnsettledAudit(parentTerminal, stopped.terminal, io, admitted.runDirectory);
|
|
1105
|
+
return { exitCode: 0, admitted, terminal };
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
return stopped;
|
|
1109
|
+
}
|
|
966
1110
|
if (resolved !== undefined && resolved.status === "escalate") {
|
|
967
1111
|
return { exitCode: 0, admitted: resolved.admitted, terminal: resolved.terminal };
|
|
968
1112
|
}
|
|
969
1113
|
if (resolved !== undefined && (resolved.status === "continue" || resolved.status === "converged")) {
|
|
970
1114
|
if (AUDITED_ROLES.has(admitted.role) && resolved.status === "converged") {
|
|
971
|
-
const terminal = await trySettlePublicSeat(
|
|
1115
|
+
const terminal = await trySettlePublicSeat(
|
|
1116
|
+
admitted,
|
|
1117
|
+
env.principalAuthority,
|
|
1118
|
+
packageFaultScope(admitted, env, io),
|
|
1119
|
+
);
|
|
972
1120
|
if (terminal?.roleOutcome.kind !== "accepted") throw new Error("pending submission is not recorded");
|
|
973
|
-
return auditSubmittedRole({ exitCode: 0, admitted, terminal }, env, io, resolved.admitted
|
|
1121
|
+
return auditSubmittedRole({ exitCode: 0, admitted, terminal }, env, io, resolved.admitted, latestQueuePayload(resolved.terminal));
|
|
974
1122
|
}
|
|
975
1123
|
return runPublicInstructionSeatResume({
|
|
976
1124
|
runId: parentRunId,
|
|
977
|
-
|
|
978
|
-
}, { ...env,
|
|
1125
|
+
summons: { instruction: readableGateItem(latestQueuePayload(resolved.terminal)) },
|
|
1126
|
+
}, { ...env, unreadableReasksSpent: 0 }, io);
|
|
979
1127
|
}
|
|
980
1128
|
const result = await dispatchAdmitted(admitted, env, { ...io, omitFailureStderrDiagnostic: true });
|
|
981
1129
|
showResumeErrorPointer(io, result.exitCode, result.terminal);
|
|
982
1130
|
return result;
|
|
983
1131
|
}
|
|
984
1132
|
|
|
1133
|
+
/**
|
|
1134
|
+
* A gate is already passed only when an officer run reviewed this submission
|
|
1135
|
+
* and its latest queue word is converged. The resumed seat's role is not itself
|
|
1136
|
+
* a pass. Unknown or unreadable evidence does not skip the gate.
|
|
1137
|
+
*/
|
|
1138
|
+
async function officerPassedCurrentSubmission(input: {
|
|
1139
|
+
readonly env: InstructionSeatRunEnv;
|
|
1140
|
+
readonly parentSessionFile: string;
|
|
1141
|
+
readonly officer: GateOfficer;
|
|
1142
|
+
readonly toolCallId: string;
|
|
1143
|
+
}): Promise<boolean> {
|
|
1144
|
+
const { env, officer } = input;
|
|
1145
|
+
const pointer = await readDirectOfficerRunPointer(input.parentSessionFile, officer);
|
|
1146
|
+
if (pointer?.runDirectory === undefined) return false;
|
|
1147
|
+
if (pointer.submissionToolCallId !== input.toolCallId) return false;
|
|
1148
|
+
const officerRunId = runIdFromRunDirectory(pointer.runDirectory);
|
|
1149
|
+
if (officerRunId === undefined) return false;
|
|
1150
|
+
let admitted: AdmittedRoleInvocation;
|
|
1151
|
+
try {
|
|
1152
|
+
const loaded = await loadResumablePublicRole(
|
|
1153
|
+
env.home,
|
|
1154
|
+
officerRunId,
|
|
1155
|
+
env.principalAuthority,
|
|
1156
|
+
);
|
|
1157
|
+
admitted = loaded.admitted;
|
|
1158
|
+
} catch {
|
|
1159
|
+
return false;
|
|
1160
|
+
}
|
|
1161
|
+
if (admitted.role !== officer) return false;
|
|
1162
|
+
// A summon binding identifies the requested review, not its outcome. An open
|
|
1163
|
+
// court (including a failed host turn) must not borrow a previous court's seal.
|
|
1164
|
+
const court = await readCurrentCourt(admitted.runDirectory);
|
|
1165
|
+
const terminal = await trySettlePublicSeat(admitted, env.principalAuthority, court);
|
|
1166
|
+
return latestQueueStatus(terminal) === "converged";
|
|
1167
|
+
}
|
|
1168
|
+
|
|
985
1169
|
/** Finished submissions enter the existing audit gate after their tool call has returned. */
|
|
986
1170
|
async function auditSubmittedRole(
|
|
987
1171
|
turn: SeatRunResult,
|
|
988
1172
|
env: InstructionSeatRunEnv,
|
|
989
1173
|
io: CliIo,
|
|
990
|
-
|
|
1174
|
+
resumedOfficer?: AdmittedRoleInvocation,
|
|
991
1175
|
passedReceipt?: unknown,
|
|
992
|
-
passedRunId?: string,
|
|
993
1176
|
): Promise<SeatRunResult> {
|
|
994
1177
|
const admitted = turn.admitted;
|
|
995
1178
|
if (admitted === undefined || !AUDITED_ROLES.has(admitted.role)
|
|
@@ -999,13 +1182,28 @@ async function auditSubmittedRole(
|
|
|
999
1182
|
const record = isRecord(accepted)
|
|
1000
1183
|
? accepted as Record<string, unknown> : undefined;
|
|
1001
1184
|
const status = admitted.role === "secretariat" ? record?.secretariatStatus : record?.status;
|
|
1185
|
+
// A gate summon already owns this conclusion's reasks. The seat must not
|
|
1186
|
+
// start another budget on the same run (parentRunPath is that summon).
|
|
1187
|
+
const gateOwnsStatusReask = typeof env.parentRunPath === "string" && env.parentRunPath.trim() !== "";
|
|
1002
1188
|
if (admitted.role === "secretariat" && status !== "converged" && status !== "escalate") {
|
|
1003
|
-
|
|
1004
|
-
|
|
1189
|
+
if (gateOwnsStatusReask) return turn;
|
|
1190
|
+
const next = withUnreadableReask(env);
|
|
1191
|
+
if (next === undefined) {
|
|
1192
|
+
const terminal = withUnsettledDirection(turn.terminal);
|
|
1193
|
+
await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, admitted.runDirectory);
|
|
1194
|
+
return { ...turn, terminal };
|
|
1195
|
+
}
|
|
1196
|
+
return runPublicInstructionSeatResume({ runId: admitted.runId, summons: { instruction: SECRETARIAT_STATUS_REASK } }, next, io);
|
|
1005
1197
|
}
|
|
1006
1198
|
if (admitted.role === "countersign" && (typeof status !== "string" || !REVIEW_QUEUE_STATUSES.has(status))) {
|
|
1007
|
-
|
|
1008
|
-
|
|
1199
|
+
if (gateOwnsStatusReask) return turn;
|
|
1200
|
+
const next = withUnreadableReask(env);
|
|
1201
|
+
if (next === undefined) {
|
|
1202
|
+
const terminal = withUnsettledDirection(turn.terminal);
|
|
1203
|
+
await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, admitted.runDirectory);
|
|
1204
|
+
return { ...turn, terminal };
|
|
1205
|
+
}
|
|
1206
|
+
return runPublicInstructionSeatResume({ runId: admitted.runId, summons: { instruction: officerConclusionReask(status) } }, next, io);
|
|
1009
1207
|
}
|
|
1010
1208
|
// Self-escalation is a valid open routing state for these seats only.
|
|
1011
1209
|
// Doctor's declared domain is completed|refused — an open "escalate" must
|
|
@@ -1017,7 +1215,7 @@ async function auditSubmittedRole(
|
|
|
1017
1215
|
|| ((admitted.role === "fixer" || admitted.role === "coder")
|
|
1018
1216
|
&& (typeof status !== "string" || !WORKER_DONE_STATUSES.has(status)));
|
|
1019
1217
|
if (skipAudit) {
|
|
1020
|
-
|
|
1218
|
+
await presentTerminal(turn.terminal, { ...io, omitFailureStderrDiagnostic: true }, admitted.runDirectory);
|
|
1021
1219
|
return turn;
|
|
1022
1220
|
}
|
|
1023
1221
|
const rows = await readRecordedSubmissionRows(admitted.projectRoot, admitted.runId, env.home);
|
|
@@ -1025,7 +1223,9 @@ async function auditSubmittedRole(
|
|
|
1025
1223
|
const toolCallId = acceptedRow?.toolCallId;
|
|
1026
1224
|
if (toolCallId === undefined) throw new Error("accepted submission has no tool call identity");
|
|
1027
1225
|
const sessionFile = env.principalAuthority.decode(admitted.principal).sessionFile;
|
|
1028
|
-
const entries = admitted.role === "doctor"
|
|
1226
|
+
const entries = admitted.role === "doctor"
|
|
1227
|
+
? await readBoundSessionEntries(sessionFile)
|
|
1228
|
+
: [];
|
|
1029
1229
|
const context: HostContext = {
|
|
1030
1230
|
cwd: admitted.projectRoot,
|
|
1031
1231
|
mode: "print",
|
|
@@ -1041,11 +1241,18 @@ async function auditSubmittedRole(
|
|
|
1041
1241
|
},
|
|
1042
1242
|
abort() {},
|
|
1043
1243
|
};
|
|
1244
|
+
const passedThisSubmission = (officer: GateOfficer) => officerPassedCurrentSubmission({
|
|
1245
|
+
env,
|
|
1246
|
+
parentSessionFile: sessionFile,
|
|
1247
|
+
officer,
|
|
1248
|
+
toolCallId,
|
|
1249
|
+
});
|
|
1044
1250
|
if (admitted.role === "doctor") {
|
|
1045
|
-
if (
|
|
1251
|
+
if (!await passedThisSubmission("auditor")) {
|
|
1046
1252
|
let lastSummon: PublicSummonResult | undefined;
|
|
1047
1253
|
const decision = await createPiDoctorAuditor()({
|
|
1048
1254
|
context, submission: accepted,
|
|
1255
|
+
...(env.autoResumeLimit === undefined ? {} : { autoResumeLimit: env.autoResumeLimit }),
|
|
1049
1256
|
...(env.signal === undefined ? {} : { signal: env.signal }),
|
|
1050
1257
|
summonAuditor: async (subject, sourceRunDirectory, signal, reask, submission) => {
|
|
1051
1258
|
const summoned = await summonPublicRole({
|
|
@@ -1065,6 +1272,7 @@ async function auditSubmittedRole(
|
|
|
1065
1272
|
if (officerSession !== undefined) {
|
|
1066
1273
|
bookDirectOfficerRunPointer({
|
|
1067
1274
|
parentSessionFile: sessionFile, officer: "auditor", sessionFile: officerSession,
|
|
1275
|
+
submissionToolCallId: toolCallId,
|
|
1068
1276
|
...(summoned.runDirectory === undefined ? {} : { runDirectory: summoned.runDirectory }),
|
|
1069
1277
|
});
|
|
1070
1278
|
}
|
|
@@ -1074,12 +1282,20 @@ async function auditSubmittedRole(
|
|
|
1074
1282
|
});
|
|
1075
1283
|
if (decision.status === "continue") {
|
|
1076
1284
|
return runPublicInstructionSeatResume({
|
|
1077
|
-
runId: admitted.runId,
|
|
1078
|
-
}, { ...env,
|
|
1285
|
+
runId: admitted.runId, summons: { instruction: readableGateItem(decision.receipt ?? decision.violations) },
|
|
1286
|
+
}, { ...env, unreadableReasksSpent: 0 }, io);
|
|
1287
|
+
}
|
|
1288
|
+
if (decision.status === "received") {
|
|
1289
|
+
if (lastSummon?.terminal === undefined) {
|
|
1290
|
+
throw new Error("doctor audit kept an unreadable reply with no terminal");
|
|
1291
|
+
}
|
|
1292
|
+
if (turn.terminal === undefined) throw new Error("doctor submission has no terminal");
|
|
1293
|
+
const terminal = await presentUnsettledAudit(turn.terminal, lastSummon.terminal, io, admitted.runDirectory);
|
|
1294
|
+
return { exitCode: 0, admitted, terminal };
|
|
1079
1295
|
}
|
|
1080
1296
|
if (decision.status !== "converged") {
|
|
1081
1297
|
if (lastSummon?.terminal !== undefined) {
|
|
1082
|
-
|
|
1298
|
+
await presentTerminal(lastSummon.terminal, { ...io, omitFailureStderrDiagnostic: true }, lastSummon.admitted?.runDirectory ?? admitted.runDirectory);
|
|
1083
1299
|
return { exitCode: lastSummon.exitCode,
|
|
1084
1300
|
...(lastSummon.admitted === undefined ? {} : { admitted: lastSummon.admitted }),
|
|
1085
1301
|
terminal: lastSummon.terminal };
|
|
@@ -1096,7 +1312,7 @@ async function auditSubmittedRole(
|
|
|
1096
1312
|
...(env.hostAdapters === undefined ? {} : { hostAdapters: env.hostAdapters }),
|
|
1097
1313
|
});
|
|
1098
1314
|
let chain: Awaited<ReturnType<typeof runJudgeGates>>;
|
|
1099
|
-
let officerRunId =
|
|
1315
|
+
let officerRunId = resumedOfficer?.runId;
|
|
1100
1316
|
const runGate = (subject: Parameters<typeof requireSubmissionGate>[0]["subject"]) =>
|
|
1101
1317
|
requireSubmissionGate({
|
|
1102
1318
|
context,
|
|
@@ -1104,6 +1320,7 @@ async function auditSubmittedRole(
|
|
|
1104
1320
|
toolCallId,
|
|
1105
1321
|
submission: accepted,
|
|
1106
1322
|
summonOfficer,
|
|
1323
|
+
...(env.autoResumeLimit === undefined ? {} : { autoResumeLimit: env.autoResumeLimit }),
|
|
1107
1324
|
...(env.signal === undefined ? {} : { signal: env.signal }),
|
|
1108
1325
|
hostActions: {
|
|
1109
1326
|
failInfrastructure(error): never { throw error; },
|
|
@@ -1112,8 +1329,7 @@ async function auditSubmittedRole(
|
|
|
1112
1329
|
});
|
|
1113
1330
|
if (admitted.role === "judge") {
|
|
1114
1331
|
chain = await runJudgeGates({
|
|
1115
|
-
gateAlreadyConverged: async (subject) =>
|
|
1116
|
-
|| (passedOfficer === "notary" && subject.kind === "judge_draft"),
|
|
1332
|
+
gateAlreadyConverged: async (subject) => passedThisSubmission(gateOfficerForSubject(subject)),
|
|
1117
1333
|
runGate,
|
|
1118
1334
|
});
|
|
1119
1335
|
} else {
|
|
@@ -1123,7 +1339,7 @@ async function auditSubmittedRole(
|
|
|
1123
1339
|
? { kind: "secretariat_verdict" as const }
|
|
1124
1340
|
: { kind: "countersign_verdict" as const };
|
|
1125
1341
|
const officer = gateOfficerForSubject(subject);
|
|
1126
|
-
if (
|
|
1342
|
+
if (await passedThisSubmission(officer)) {
|
|
1127
1343
|
chain = { status: "converged", passes: [] };
|
|
1128
1344
|
} else {
|
|
1129
1345
|
const pass = await runGate(subject);
|
|
@@ -1137,10 +1353,18 @@ async function auditSubmittedRole(
|
|
|
1137
1353
|
receipt: pass.receipt,
|
|
1138
1354
|
...(pass.runId === undefined ? {} : { runId: pass.runId }),
|
|
1139
1355
|
...(pass.runDirectory === undefined ? {} : { runDirectory: pass.runDirectory }),
|
|
1356
|
+
...(pass.terminal === undefined ? {} : { terminal: pass.terminal }),
|
|
1140
1357
|
}],
|
|
1141
1358
|
};
|
|
1142
1359
|
}
|
|
1143
1360
|
}
|
|
1361
|
+
if (chain.status === "needs_reask") {
|
|
1362
|
+
const officerTerminal = chain.passes.at(-1)?.terminal;
|
|
1363
|
+
if (officerTerminal === undefined) throw new Error("unreadable audit has no terminal result");
|
|
1364
|
+
if (turn.terminal === undefined) throw new Error("audited submission has no terminal");
|
|
1365
|
+
const terminal = await presentUnsettledAudit(turn.terminal, officerTerminal, io, admitted.runDirectory);
|
|
1366
|
+
return { exitCode: 0, admitted, terminal };
|
|
1367
|
+
}
|
|
1144
1368
|
if (chain.status === "escalate") {
|
|
1145
1369
|
const escalation = chain.passes.at(-1);
|
|
1146
1370
|
const escalatedRunId = escalation?.runId
|
|
@@ -1148,16 +1372,20 @@ async function auditSubmittedRole(
|
|
|
1148
1372
|
? undefined : runIdFromRunDirectory(escalation.runDirectory));
|
|
1149
1373
|
if (escalatedRunId === undefined) throw new Error("escalated audit has no resumable run identity");
|
|
1150
1374
|
const officer = await loadResumablePublicRole(env.home, escalatedRunId, env.principalAuthority);
|
|
1151
|
-
const terminal = await trySettlePublicSeat(
|
|
1375
|
+
const terminal = await trySettlePublicSeat(
|
|
1376
|
+
officer.admitted,
|
|
1377
|
+
env.principalAuthority,
|
|
1378
|
+
{ ...await readCurrentCourt(officer.admitted.runDirectory), ...packageFaultScope(officer.admitted, env, io) },
|
|
1379
|
+
);
|
|
1152
1380
|
if (terminal === undefined) throw new Error("escalated audit has no terminal result");
|
|
1153
|
-
io.
|
|
1381
|
+
await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, officer.admitted.runDirectory);
|
|
1154
1382
|
return { exitCode: 0, admitted: officer.admitted, terminal };
|
|
1155
1383
|
}
|
|
1156
1384
|
if (chain.status === "continue") {
|
|
1157
1385
|
return runPublicInstructionSeatResume({
|
|
1158
1386
|
runId: admitted.runId,
|
|
1159
|
-
|
|
1160
|
-
}, { ...env,
|
|
1387
|
+
summons: { instruction: readableGateItem(chain.passes.at(-1)?.receipt) },
|
|
1388
|
+
}, { ...env, unreadableReasksSpent: 0 }, io);
|
|
1161
1389
|
}
|
|
1162
1390
|
if (admitted.role === "secretariat") {
|
|
1163
1391
|
const pass = chain.passes.at(-1);
|
|
@@ -1174,8 +1402,13 @@ async function auditSubmittedRole(
|
|
|
1174
1402
|
// Audit only adds gate rounds and, for 中书省, the officer fact. A second
|
|
1175
1403
|
// settle would republish the same attempt.
|
|
1176
1404
|
if (turn.terminal === undefined) throw new Error(`audited ${admitted.role} submission did not settle`);
|
|
1177
|
-
const terminal = await attachPostAuditProjection(
|
|
1405
|
+
const terminal = await attachPostAuditProjection(
|
|
1406
|
+
admitted,
|
|
1407
|
+
env.principalAuthority,
|
|
1408
|
+
turn.terminal,
|
|
1409
|
+
packageFaultScope(admitted, env, io),
|
|
1410
|
+
);
|
|
1178
1411
|
turn = { ...turn, terminal };
|
|
1179
|
-
io.
|
|
1412
|
+
await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, admitted.runDirectory);
|
|
1180
1413
|
return turn;
|
|
1181
1414
|
}
|