@akagilnc/pi-workflow-roles 0.1.5714 → 0.1.5753
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/dist/acp-host/production-host.js +517 -516
- package/dist/analyst-gate-cycles-read.js +7 -6
- package/dist/archivist-record-pointer.js +9 -45
- package/dist/auditor-soul.js +7 -5
- package/dist/external-host-turn-loop.js +2 -16
- package/dist/gatekeeper-role.js +14 -1
- package/dist/headless-host/production-host.js +517 -516
- package/dist/judge-role.js +1 -1
- package/dist/migrate-book-topology.js +61 -51
- package/dist/navigator-public-session.js +17 -8
- package/dist/notary-contracts.js +2 -2
- package/dist/notary-source-run.js +2 -2
- package/dist/packaged-role-registry.js +0 -10
- package/dist/public-cli/cli.js +13 -6
- package/dist/public-cli/instruction-seat-run.js +157 -138
- package/dist/public-cli/invocation.js +35 -0
- package/dist/public-cli/main.js +497 -505
- package/dist/public-cli/post-admission.js +11 -12
- package/dist/public-cli/run-lifecycle.js +56 -34
- package/dist/public-cli/seat-ticket-binding.js +8 -7
- package/dist/public-cli/settlement.js +4 -126
- package/dist/public-cli/terminal.js +3 -3
- package/dist/public-role-summons.js +14 -6
- package/dist/review-submission.js +47 -14
- package/dist/role-run-relocation.js +4 -3
- package/dist/role-submission-declarations.js +5 -5
- package/dist/run-dossier.js +6 -21
- package/dist/run-terminal-artifacts.js +11 -0
- package/dist/secretariat-contracts.js +0 -4
- package/dist/submission-gate.js +58 -42
- package/dist/submission-ledger.js +3 -2
- package/package.json +1 -1
- package/souls/notary.md +6 -5
- package/src/analyst-gate-cycles-read.ts +7 -6
- package/src/analyst-ledger.ts +2 -2
- package/src/archivist-record-pointer.ts +10 -64
- package/src/auditor-soul.ts +7 -5
- package/src/countersign-role.ts +5 -5
- package/src/external-host-turn-loop.ts +2 -23
- package/src/gatekeeper-role.ts +24 -3
- package/src/judge-role.ts +1 -1
- package/src/navigator-public-session.ts +22 -10
- package/src/notary-contracts.ts +3 -2
- package/src/notary-source-run.ts +2 -7
- package/src/packaged-role-registry.ts +0 -13
- package/src/public-cli/cli.ts +18 -4
- package/src/public-cli/instruction-seat-run.ts +213 -155
- package/src/public-cli/invocation.ts +39 -0
- package/src/public-cli/post-admission.ts +11 -9
- package/src/public-cli/run-lifecycle.ts +80 -33
- package/src/public-cli/seat-ticket-binding.ts +9 -7
- package/src/public-cli/settlement.ts +3 -167
- package/src/public-cli/terminal.ts +3 -3
- package/src/public-role-summons.ts +40 -12
- package/src/review-submission.ts +72 -21
- package/src/role-run-relocation.ts +4 -3
- package/src/role-runtime.ts +3 -3
- package/src/role-submission-declarations.ts +5 -5
- package/src/run-dossier.ts +7 -19
- package/src/run-terminal-artifacts.ts +13 -0
- package/src/secretariat-contracts.ts +0 -19
- package/src/submission-gate.ts +75 -62
- package/src/submission-ledger.ts +3 -6
|
@@ -8,33 +8,30 @@ import { MISSING_TICKET_REASK_MATERIAL } from "../report-ticket-tool.js";
|
|
|
8
8
|
import { isUnboundRunDirectory, sessionFileOf } from "../role-run-placement.js";
|
|
9
9
|
import { rewriteRunDirectoryPathValue } from "../role-run-relocation.js";
|
|
10
10
|
import { readPackageMaterial } from "../session-opening-materials.js";
|
|
11
|
-
import { bookDirectOfficerRunPointer, readDirectOfficerRunPointer } from "../archivist-record-pointer.js";
|
|
12
11
|
import { createPiDoctorAuditor } from "../doctor-auditor.js";
|
|
13
12
|
import { officerConclusionReask, gateOfficerForSubject } from "../gatekeeper-role.js";
|
|
14
13
|
import { receivedDiscriminator } from "../submission-errors.js";
|
|
15
14
|
import { REVIEW_QUEUE_STATUSES } from "../review-submission.js";
|
|
16
|
-
import { runJudgeGates } from "../judge-role.js";
|
|
15
|
+
import { JUDGE_GATES, runJudgeGates } from "../judge-role.js";
|
|
17
16
|
import { WORKER_DONE_STATUSES } from "../worker-submission-contracts.js";
|
|
18
|
-
import { SECRETARIAT_GATE_OFFICER_ENTRY_TYPE } from "../secretariat-contracts.js";
|
|
19
17
|
import { readableGateItem } from "../readable-gate-item.js";
|
|
20
18
|
import { deliveryLimitFromConfig } from "../receipt-delivery-policy.js";
|
|
21
19
|
import { runIdFromRunDirectory } from "../run-terminal-artifacts.js";
|
|
22
20
|
import { createDefaultGateOfficerSummon, requireSubmissionGate } from "../submission-gate.js";
|
|
23
21
|
import { readRecordedSubmissionRows } from "../submission-ledger.js";
|
|
24
22
|
import { summonPublicRole } from "../public-role-summons.js";
|
|
25
|
-
import { sessionFileFromPublicSummon } from "../session-assistant-usage.js";
|
|
26
23
|
import { latestQueuePayload, latestQueueStatus, } from "../submission-gate.js";
|
|
27
24
|
import { isSafePositiveTicketNumber, readBoardTicketNumber, } from "../run-ticket-number.js";
|
|
28
25
|
import { NotarySourceRunError, resolveNotarySourceRunLocator } from "../notary-source-run.js";
|
|
29
26
|
import { packagedAdmitsCountersign, packagedBindsBoardTicket, packagedRebindSourceOnResume, packagedRoleMetadata, } from "../packaged-role-registry.js";
|
|
30
27
|
import { readAuditorResumeBinding } from "../auditor-soul.js";
|
|
31
28
|
import { CliUsageError } from "./cli-errors.js";
|
|
32
|
-
import { admitPublicRole, bindAdmittedTicketNumber, appendCallerFileFlagPaths, buildInstructionTransportPrompt, materializeCountersignInvocation, persistAdmittedSourceRunPath, recordAdmittedCorrelation, recordChildDiaristRun, relocateAdmittedRunToTicket, } from "./invocation.js";
|
|
29
|
+
import { admitPublicRole, admittedSourceRunPath, bindAdmittedTicketNumber, appendCallerFileFlagPaths, buildInstructionTransportPrompt, materializeCountersignInvocation, persistAdmittedAuditedSubmissionToolCallId, persistAdmittedSourceRunPath, readAdmittedAuditedSubmissionToolCallId, recordAdmittedCorrelation, recordChildDiaristRun, relocateAdmittedRunToTicket, } from "./invocation.js";
|
|
33
30
|
import { bindDiaristAssertedTicketNumber, presentControlledFailure, packageFaultNoteFor, prepareSummonsResumeMaterials, roleTurnOptions, runPostAdmissionOneShot, runPostAdmissionResumable, runPostAdmissionSeatResume, showResumeErrorPointer, resumeTurnRequestProjectionOptions, } from "./post-admission.js";
|
|
34
31
|
import { presentTerminal } from "./auto-resume.js";
|
|
35
32
|
import { buildAutoResumeContinuationPrompt, loadResumablePublicRole, markRunAdmitted, readCurrentCourt, } from "./run-lifecycle.js";
|
|
36
33
|
import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.js";
|
|
37
|
-
import { presentStructuralRejection, readBoundSessionEntries,
|
|
34
|
+
import { presentStructuralRejection, readBoundSessionEntries, trySettlePublicSeat, } from "./settlement.js";
|
|
38
35
|
import { warnMissingMethodSkills } from "./machine-method-skills.js";
|
|
39
36
|
import { formatTerminalResult, isLawfulTypedTerminalOutcome, } from "./terminal.js";
|
|
40
37
|
import { admittedSeatTurnDetails, projectRoleTurnRequest, requiredMethodSkills, } from "./turn-request.js";
|
|
@@ -120,17 +117,14 @@ async function presentOriginalVolume(held, terminal, io, runDirectory) {
|
|
|
120
117
|
for (const value of held)
|
|
121
118
|
io.stdout(value);
|
|
122
119
|
}
|
|
123
|
-
/**
|
|
124
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Mark this leg's terminal that subsequent audit did not settle a queue word.
|
|
122
|
+
* Other-seat receipts / run ids stay on those runs — not copied here (#1195).
|
|
123
|
+
*/
|
|
124
|
+
function withUnsettledDirection(parent) {
|
|
125
125
|
const outcome = parent.roleOutcome;
|
|
126
126
|
if (outcome.kind !== "accepted" && outcome.kind !== "audit_escalation")
|
|
127
127
|
return parent;
|
|
128
|
-
const officerOutcome = officer?.roleOutcome;
|
|
129
|
-
const officerPayloads = officer?.submissions !== undefined && officer.submissions.length > 0
|
|
130
|
-
? officer.submissions
|
|
131
|
-
: officerOutcome !== undefined && officerOutcome.kind !== "no_receipt"
|
|
132
|
-
? officerOutcome.payloads ?? []
|
|
133
|
-
: [];
|
|
134
128
|
return {
|
|
135
129
|
...parent,
|
|
136
130
|
roleOutcome: {
|
|
@@ -139,9 +133,6 @@ function withUnsettledDirection(parent, officer) {
|
|
|
139
133
|
...(outcome.decisiveFacts ?? {}),
|
|
140
134
|
directionUnsettled: true,
|
|
141
135
|
subsequentAudit: "incomplete",
|
|
142
|
-
...(officerOutcome === undefined ? {} : { officerRole: officerOutcome.role }),
|
|
143
|
-
...(officer?.runId === undefined ? {} : { officerRunId: officer.runId }),
|
|
144
|
-
...(officerPayloads.length === 0 ? {} : { officerPayloads }),
|
|
145
136
|
},
|
|
146
137
|
},
|
|
147
138
|
};
|
|
@@ -154,11 +145,13 @@ function heldUnreadableTerminal(terminal) {
|
|
|
154
145
|
const status = latestQueueStatus(terminal);
|
|
155
146
|
return typeof status !== "string" || !REVIEW_QUEUE_STATUSES.has(status);
|
|
156
147
|
}
|
|
157
|
-
|
|
158
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Present the actual audit seat's volume for an unreadable conclusion (ADR 0055).
|
|
150
|
+
* Parent is not given a copy of the officer receipt (#1195).
|
|
151
|
+
*/
|
|
152
|
+
async function presentUnsettledOfficer(officer, io, runDirectory) {
|
|
153
|
+
const terminal = withUnsettledDirection(officer);
|
|
159
154
|
await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, runDirectory);
|
|
160
|
-
if (officer !== undefined)
|
|
161
|
-
await presentTerminal(officer, { ...io, omitFailureStderrDiagnostic: true }, runDirectory);
|
|
162
155
|
return terminal;
|
|
163
156
|
}
|
|
164
157
|
async function reaskUnreadablePostSubmissionStatus(admitted, terminal, env, io, message = unreadablePostSubmissionStatus(admitted, terminal)) {
|
|
@@ -167,7 +160,11 @@ async function reaskUnreadablePostSubmissionStatus(admitted, terminal, env, io,
|
|
|
167
160
|
const next = withUnreadableReask(env);
|
|
168
161
|
if (next === undefined)
|
|
169
162
|
return UNREADABLE_REASK_EXHAUSTED;
|
|
170
|
-
return runPublicInstructionSeatResume({
|
|
163
|
+
return runPublicInstructionSeatResume({
|
|
164
|
+
runId: admitted.runId,
|
|
165
|
+
runDirectory: admitted.runDirectory,
|
|
166
|
+
summons: { instruction: message },
|
|
167
|
+
}, next, io);
|
|
171
168
|
}
|
|
172
169
|
/**
|
|
173
170
|
* #1171: sealed submission still leaves the leg unbound → soft reask once.
|
|
@@ -204,7 +201,11 @@ async function reaskMissingTicketOnce(admitted, terminal, env, io) {
|
|
|
204
201
|
softTicketReaskTurn: true,
|
|
205
202
|
softTicketReaskOwnership,
|
|
206
203
|
};
|
|
207
|
-
const result = await runPublicInstructionSeatResume({
|
|
204
|
+
const result = await runPublicInstructionSeatResume({
|
|
205
|
+
runId: admitted.runId,
|
|
206
|
+
runDirectory: admitted.runDirectory,
|
|
207
|
+
summons: { instruction },
|
|
208
|
+
}, softReaskEnv, io);
|
|
208
209
|
if (softTicketReaskOwnership.sealedSubstitute
|
|
209
210
|
|| terminalCarriesSealedSubmission(result.terminal)) {
|
|
210
211
|
return { kind: "nested_owns", result };
|
|
@@ -347,6 +348,7 @@ async function loadLedgerPeerBody(sourceRunDirectory, projectRoot, home) {
|
|
|
347
348
|
* One delivery rule for review-seat dialogue on new turns and same-parent resume
|
|
348
349
|
* (#1166 / ADR 0085 / ADR 0087): explicit reask → non-empty caller dispatch →
|
|
349
350
|
* source-only ledger peer body. Identity stays in startup materials.
|
|
351
|
+
* #1195: ticket-court notary skips peer-body preload (countersign source only).
|
|
350
352
|
*/
|
|
351
353
|
async function resolveReviewSeatDialogueBody(input) {
|
|
352
354
|
const reask = input.reask;
|
|
@@ -355,26 +357,26 @@ async function resolveReviewSeatDialogueBody(input) {
|
|
|
355
357
|
const caller = input.callerInstruction ?? "";
|
|
356
358
|
if (caller.length > 0)
|
|
357
359
|
return caller;
|
|
358
|
-
const sourceRunPath = input
|
|
359
|
-
if (sourceRunPath ===
|
|
360
|
+
const sourceRunPath = admittedSourceRunPath(input)?.trim();
|
|
361
|
+
if (sourceRunPath === undefined)
|
|
360
362
|
return undefined;
|
|
363
|
+
if (input.role === "notary") {
|
|
364
|
+
const { isTicketCourtCountersignSource } = await import("../run-terminal-artifacts.js");
|
|
365
|
+
if (isTicketCourtCountersignSource(sourceRunPath))
|
|
366
|
+
return undefined;
|
|
367
|
+
}
|
|
361
368
|
return await loadLedgerPeerBody(sourceRunPath, input.projectRoot, input.home);
|
|
362
369
|
}
|
|
363
|
-
function admittedSourceRunPath(admitted) {
|
|
364
|
-
return "sourceRunPath" in admitted
|
|
365
|
-
&& typeof admitted.sourceRunPath === "string"
|
|
366
|
-
? admitted.sourceRunPath.trim()
|
|
367
|
-
: "";
|
|
368
|
-
}
|
|
369
370
|
async function resolveInitialPrompt(admitted, env) {
|
|
370
371
|
const record = roleRecord(admitted.role);
|
|
371
372
|
if ("reaskPrompt" in record && record.reaskPrompt === true) {
|
|
372
373
|
const sourceRunPath = admittedSourceRunPath(admitted);
|
|
373
374
|
const reask = env.reviewReask ?? env.gateReviewInstruction;
|
|
374
375
|
const body = await resolveReviewSeatDialogueBody({
|
|
376
|
+
role: admitted.role,
|
|
375
377
|
...(reask === undefined ? {} : { reask }),
|
|
376
378
|
callerInstruction: admitted.instruction,
|
|
377
|
-
...(sourceRunPath ===
|
|
379
|
+
...(sourceRunPath === undefined ? {} : { sourceRunPath }),
|
|
378
380
|
projectRoot: admitted.projectRoot,
|
|
379
381
|
home: env.home,
|
|
380
382
|
});
|
|
@@ -602,16 +604,21 @@ function resumeSameParentInstructionSeat(input) {
|
|
|
602
604
|
...(input.ticketNumber === undefined ? {} : { ticketNumber: input.ticketNumber }),
|
|
603
605
|
freshSummons: input.env.freshSummons,
|
|
604
606
|
summons: input.summons,
|
|
605
|
-
resume: (runId, materials) => runPublicInstructionSeatResume({
|
|
607
|
+
resume: (runId, materials, runDirectory) => runPublicInstructionSeatResume({
|
|
608
|
+
runId,
|
|
609
|
+
runDirectory,
|
|
610
|
+
...(materials === undefined ? {} : { summons: materials }),
|
|
611
|
+
}, input.env, input.io),
|
|
606
612
|
});
|
|
607
613
|
}
|
|
608
614
|
/**
|
|
609
615
|
* Same delivery rule as resolveInitialPrompt for same-parent resume summons.
|
|
610
616
|
* Reask / explicit caller text / source-only ledger peer — one authority.
|
|
611
617
|
*/
|
|
612
|
-
async function sameParentDialogue(env, fallback, sourceRunPath, projectRoot) {
|
|
618
|
+
async function sameParentDialogue(env, fallback, sourceRunPath, projectRoot, role) {
|
|
613
619
|
const reask = env.reviewReask ?? env.gateReviewInstruction;
|
|
614
620
|
const body = await resolveReviewSeatDialogueBody({
|
|
621
|
+
role,
|
|
615
622
|
...(reask === undefined ? {} : { reask }),
|
|
616
623
|
callerInstruction: fallback.instruction,
|
|
617
624
|
sourceRunPath,
|
|
@@ -753,6 +760,7 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
|
|
|
753
760
|
let auditorSource;
|
|
754
761
|
let auditorTicket;
|
|
755
762
|
let resolvedNotarySource;
|
|
763
|
+
let instructionSourceRunPath;
|
|
756
764
|
if (record.sameParent === "subject-source") {
|
|
757
765
|
if (parsed.subject === undefined) {
|
|
758
766
|
presentStructuralRejection(new CliUsageError("auditor --subject requires judge|doctor"), io);
|
|
@@ -780,7 +788,7 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
|
|
|
780
788
|
...(await sameParentDialogue(env, {
|
|
781
789
|
instruction: parsed.instruction ?? "",
|
|
782
790
|
instructionEmpty: (parsed.instruction ?? "").length === 0,
|
|
783
|
-
}, sourceDirectory, projectRoot)),
|
|
791
|
+
}, sourceDirectory, projectRoot, role)),
|
|
784
792
|
attachmentPaths: parsed.attachmentPaths ?? [],
|
|
785
793
|
};
|
|
786
794
|
const resumed = await withAuditorSoulEnv({
|
|
@@ -801,9 +809,8 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
|
|
|
801
809
|
if (record.sameParent === "source-run") {
|
|
802
810
|
// #1166: structured --source-run only. Instruction bytes stay opaque caller/peer text.
|
|
803
811
|
if (parsed.sourceRun !== undefined) {
|
|
804
|
-
let parentRunPath;
|
|
805
812
|
try {
|
|
806
|
-
|
|
813
|
+
instructionSourceRunPath = (await resolveNotarySourceRunLocator({
|
|
807
814
|
projectRoot,
|
|
808
815
|
sourceRun: parsed.sourceRun,
|
|
809
816
|
home: env.home,
|
|
@@ -816,12 +823,13 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
|
|
|
816
823
|
}
|
|
817
824
|
throw error;
|
|
818
825
|
}
|
|
826
|
+
const parentRunPath = instructionSourceRunPath;
|
|
819
827
|
const summons = {
|
|
820
828
|
sourceRunPath: parentRunPath,
|
|
821
829
|
...(await sameParentDialogue(env, {
|
|
822
830
|
instruction: parsed.instruction ?? "",
|
|
823
831
|
instructionEmpty: (parsed.instruction ?? "").length === 0,
|
|
824
|
-
}, parentRunPath, projectRoot)),
|
|
832
|
+
}, parentRunPath, projectRoot, role)),
|
|
825
833
|
attachmentPaths: parsed.attachmentPaths ?? [],
|
|
826
834
|
};
|
|
827
835
|
const resumed = await resumeSameParentInstructionSeat({
|
|
@@ -855,7 +863,7 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
|
|
|
855
863
|
const summons = {
|
|
856
864
|
sourceRunPath: source.runDirectory,
|
|
857
865
|
sourceRun: source,
|
|
858
|
-
...(await sameParentDialogue(env, { instruction: "", instructionEmpty: true }, source.runDirectory, projectRoot)),
|
|
866
|
+
...(await sameParentDialogue(env, { instruction: "", instructionEmpty: true }, source.runDirectory, projectRoot, role)),
|
|
859
867
|
};
|
|
860
868
|
resolvedNotarySource = source;
|
|
861
869
|
const resumed = await resumeSameParentInstructionSeat({
|
|
@@ -883,14 +891,9 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
|
|
|
883
891
|
return rejected;
|
|
884
892
|
throw error;
|
|
885
893
|
}
|
|
886
|
-
if (
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
sourceRun: parsed.sourceRun,
|
|
890
|
-
home: env.home,
|
|
891
|
-
})).runDirectory;
|
|
892
|
-
await persistAdmittedSourceRunPath(admitted, parentRunPath);
|
|
893
|
-
admitted = { ...admitted, sourceRunPath: parentRunPath };
|
|
894
|
+
if (instructionSourceRunPath !== undefined) {
|
|
895
|
+
await persistAdmittedSourceRunPath(admitted, instructionSourceRunPath);
|
|
896
|
+
admitted = { ...admitted, sourceRunPath: instructionSourceRunPath };
|
|
894
897
|
}
|
|
895
898
|
if (record.sameParent === "subject-source" && auditorSource !== undefined) {
|
|
896
899
|
await persistAdmittedSourceRunPath(admitted, auditorSource, auditorSubject);
|
|
@@ -941,6 +944,7 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
|
|
|
941
944
|
return runAdmitted();
|
|
942
945
|
}
|
|
943
946
|
export async function runPublicInstructionSeatResume(request, env, io) {
|
|
947
|
+
let selectedRequest = request;
|
|
944
948
|
const resume = async () => {
|
|
945
949
|
const held = [];
|
|
946
950
|
const turnIo = {
|
|
@@ -948,11 +952,11 @@ export async function runPublicInstructionSeatResume(request, env, io) {
|
|
|
948
952
|
stderr: io.stderr,
|
|
949
953
|
};
|
|
950
954
|
const result = await runPostAdmissionSeatResume({
|
|
951
|
-
request,
|
|
955
|
+
request: selectedRequest,
|
|
952
956
|
env,
|
|
953
957
|
io: turnIo,
|
|
954
958
|
load: async (effective) => {
|
|
955
|
-
const loaded = await loadResumablePublicRole(env.home, effective.runId, env.principalAuthority);
|
|
959
|
+
const loaded = await loadResumablePublicRole(env.home, effective.runId, env.principalAuthority, effective.runDirectory === undefined ? undefined : { runDirectory: effective.runDirectory });
|
|
956
960
|
if (packagedRebindSourceOnResume(loaded.admitted.role)
|
|
957
961
|
&& effective.summons?.sourceRunPath !== undefined
|
|
958
962
|
&& effective.summons.sourceRun !== undefined) {
|
|
@@ -990,9 +994,10 @@ export async function runPublicInstructionSeatResume(request, env, io) {
|
|
|
990
994
|
};
|
|
991
995
|
let binding;
|
|
992
996
|
try {
|
|
993
|
-
const loaded = await loadResumablePublicRole(env.home, request.runId, env.principalAuthority);
|
|
997
|
+
const loaded = await loadResumablePublicRole(env.home, request.runId, env.principalAuthority, request.runDirectory === undefined ? undefined : { runDirectory: request.runDirectory });
|
|
998
|
+
selectedRequest = { ...request, runDirectory: loaded.admitted.runDirectory };
|
|
994
999
|
binding = loaded.admitted.role === "auditor"
|
|
995
|
-
? await readAuditorResumeBinding(loaded.admitted
|
|
1000
|
+
? await readAuditorResumeBinding(loaded.admitted)
|
|
996
1001
|
: undefined;
|
|
997
1002
|
}
|
|
998
1003
|
catch (error) {
|
|
@@ -1060,23 +1065,25 @@ async function queueConclusionFromChild(child, env, io) {
|
|
|
1060
1065
|
}
|
|
1061
1066
|
/** Continue the parent once a child has submitted. The child words ride the existing resume. */
|
|
1062
1067
|
export async function continueParentAfterChild(parentRunId, child, env, io) {
|
|
1063
|
-
const
|
|
1068
|
+
const knownParentDirectory = admittedSourceRunPath(child);
|
|
1069
|
+
const loaded = await loadResumablePublicRole(env.home, parentRunId, env.principalAuthority, knownParentDirectory === undefined ? undefined : { runDirectory: knownParentDirectory });
|
|
1064
1070
|
if (loaded.run.state !== "admitted" && !AUDITED_ROLES.has(loaded.admitted.role)) {
|
|
1065
|
-
return runPublicInstructionSeatResume({
|
|
1071
|
+
return runPublicInstructionSeatResume({
|
|
1072
|
+
runId: parentRunId,
|
|
1073
|
+
runDirectory: loaded.admitted.runDirectory,
|
|
1074
|
+
}, env, io);
|
|
1066
1075
|
}
|
|
1067
1076
|
const admitted = loaded.admitted;
|
|
1068
1077
|
const resolved = await queueConclusionFromChild(child, env, io);
|
|
1069
1078
|
if (resolved !== undefined && "stop" in resolved) {
|
|
1070
1079
|
const stopped = resolved.stop;
|
|
1080
|
+
// Unreadable child conclusion stays on that seat — resume 审核席本人 (ADR 0055 / #1195).
|
|
1071
1081
|
if (stopped.exitCode === 0
|
|
1072
1082
|
&& heldUnreadableTerminal(stopped.terminal)
|
|
1073
|
-
&& stopped.terminal !== undefined
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
const terminal = await presentUnsettledAudit(parentTerminal, stopped.terminal, io, admitted.runDirectory);
|
|
1078
|
-
return { exitCode: 0, admitted, terminal };
|
|
1079
|
-
}
|
|
1083
|
+
&& stopped.terminal !== undefined
|
|
1084
|
+
&& stopped.admitted !== undefined) {
|
|
1085
|
+
const terminal = await presentUnsettledOfficer(stopped.terminal, io, stopped.admitted.runDirectory);
|
|
1086
|
+
return { exitCode: 0, admitted: stopped.admitted, terminal };
|
|
1080
1087
|
}
|
|
1081
1088
|
return stopped;
|
|
1082
1089
|
}
|
|
@@ -1088,10 +1095,14 @@ export async function continueParentAfterChild(parentRunId, child, env, io) {
|
|
|
1088
1095
|
const terminal = await trySettlePublicSeat(admitted, env.principalAuthority, { ...await readCurrentCourt(admitted.runDirectory), ...packageFaultScope(admitted, env, io) });
|
|
1089
1096
|
if (terminal?.roleOutcome.kind !== "accepted")
|
|
1090
1097
|
throw new Error("pending submission is not recorded");
|
|
1091
|
-
|
|
1098
|
+
// Live child only when admitted-request.auditedSubmissionToolCallId matches
|
|
1099
|
+
// the parent seal under audit (#1195 option 1 / owner 00644146).
|
|
1100
|
+
const live = liveChildForCurrentParentSeal(terminal, resolved.admitted, latestQueuePayload(resolved.terminal));
|
|
1101
|
+
return auditSubmittedRole({ exitCode: 0, admitted, terminal }, env, io, live?.officer, live?.receipt);
|
|
1092
1102
|
}
|
|
1093
1103
|
return runPublicInstructionSeatResume({
|
|
1094
1104
|
runId: parentRunId,
|
|
1105
|
+
runDirectory: admitted.runDirectory,
|
|
1095
1106
|
summons: { instruction: readableGateItem(latestQueuePayload(resolved.terminal)) },
|
|
1096
1107
|
}, envForCourtContinue(env), io);
|
|
1097
1108
|
}
|
|
@@ -1100,35 +1111,39 @@ export async function continueParentAfterChild(parentRunId, child, env, io) {
|
|
|
1100
1111
|
return result;
|
|
1101
1112
|
}
|
|
1102
1113
|
/**
|
|
1103
|
-
*
|
|
1104
|
-
*
|
|
1105
|
-
*
|
|
1114
|
+
* Hand continueParentAfterChild's live child to audit only when the child's own
|
|
1115
|
+
* admitted-request records this parent seal's toolCallId (#1195 option 1).
|
|
1116
|
+
* Read failures propagate — never wash into "no match".
|
|
1106
1117
|
*/
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1118
|
+
function liveChildForCurrentParentSeal(parentTerminal, child, receipt) {
|
|
1119
|
+
if (receipt === undefined)
|
|
1120
|
+
return undefined;
|
|
1121
|
+
const parentSealId = parentTerminal.submissionToolCallId?.trim() ?? "";
|
|
1122
|
+
if (parentSealId === "")
|
|
1123
|
+
return undefined;
|
|
1124
|
+
const childSealId = readAdmittedAuditedSubmissionToolCallId(child.runDirectory);
|
|
1125
|
+
if (childSealId !== parentSealId)
|
|
1126
|
+
return undefined;
|
|
1127
|
+
return { officer: child, receipt };
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* Gate already satisfied for this routing turn when continueParentAfterChild
|
|
1131
|
+
* handed a live converged child that belongs to this parent seal, or — for a
|
|
1132
|
+
* multi-gate chain on that same seal — an earlier gate before that child
|
|
1133
|
+
* (ADR 0003 remaining gates). Parent-side officer pointers are not consulted (#1195).
|
|
1134
|
+
*/
|
|
1135
|
+
function officerSatisfiedByLiveChild(officer, resumedOfficer, passedReceipt,
|
|
1136
|
+
/** Ordered officers of this parent's gate chain; earlier than live child = done. */
|
|
1137
|
+
chainOrder) {
|
|
1138
|
+
if (resumedOfficer === undefined || passedReceipt === undefined)
|
|
1123
1139
|
return false;
|
|
1124
|
-
|
|
1125
|
-
|
|
1140
|
+
if (resumedOfficer.role === officer)
|
|
1141
|
+
return true;
|
|
1142
|
+
if (chainOrder === undefined)
|
|
1126
1143
|
return false;
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
const terminal = await trySettlePublicSeat(admitted, env.principalAuthority, court);
|
|
1131
|
-
return latestQueueStatus(terminal) === "converged";
|
|
1144
|
+
const childIndex = chainOrder.indexOf(resumedOfficer.role);
|
|
1145
|
+
const officerIndex = chainOrder.indexOf(officer);
|
|
1146
|
+
return childIndex >= 0 && officerIndex >= 0 && officerIndex < childIndex;
|
|
1132
1147
|
}
|
|
1133
1148
|
/** Finished submissions enter the existing audit gate after their tool call has returned. */
|
|
1134
1149
|
async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt) {
|
|
@@ -1156,7 +1171,11 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
|
|
|
1156
1171
|
await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, admitted.runDirectory);
|
|
1157
1172
|
return { ...turn, terminal };
|
|
1158
1173
|
}
|
|
1159
|
-
return runPublicInstructionSeatResume({
|
|
1174
|
+
return runPublicInstructionSeatResume({
|
|
1175
|
+
runId: admitted.runId,
|
|
1176
|
+
runDirectory: admitted.runDirectory,
|
|
1177
|
+
summons: { instruction: SECRETARIAT_STATUS_REASK },
|
|
1178
|
+
}, next, io);
|
|
1160
1179
|
}
|
|
1161
1180
|
if (admitted.role === "countersign" && (typeof status !== "string" || !REVIEW_QUEUE_STATUSES.has(status))) {
|
|
1162
1181
|
if (gateOwnsStatusReask)
|
|
@@ -1167,7 +1186,11 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
|
|
|
1167
1186
|
await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, admitted.runDirectory);
|
|
1168
1187
|
return { ...turn, terminal };
|
|
1169
1188
|
}
|
|
1170
|
-
return runPublicInstructionSeatResume({
|
|
1189
|
+
return runPublicInstructionSeatResume({
|
|
1190
|
+
runId: admitted.runId,
|
|
1191
|
+
runDirectory: admitted.runDirectory,
|
|
1192
|
+
summons: { instruction: officerConclusionReask(status) },
|
|
1193
|
+
}, next, io);
|
|
1171
1194
|
}
|
|
1172
1195
|
// Self-escalation is a valid open routing state for these seats only.
|
|
1173
1196
|
// Doctor's declared domain is completed|refused — an open "escalate" must
|
|
@@ -1208,14 +1231,9 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
|
|
|
1208
1231
|
},
|
|
1209
1232
|
abort() { },
|
|
1210
1233
|
};
|
|
1211
|
-
const
|
|
1212
|
-
env,
|
|
1213
|
-
parentSessionFile: sessionFile,
|
|
1214
|
-
officer,
|
|
1215
|
-
toolCallId,
|
|
1216
|
-
});
|
|
1234
|
+
const gateSatisfied = (officer, chainOrder) => officerSatisfiedByLiveChild(officer, resumedOfficer, passedReceipt, chainOrder);
|
|
1217
1235
|
if (admitted.role === "doctor") {
|
|
1218
|
-
if (!
|
|
1236
|
+
if (!gateSatisfied("auditor")) {
|
|
1219
1237
|
let lastSummon;
|
|
1220
1238
|
const decision = await createPiDoctorAuditor()({
|
|
1221
1239
|
context, submission: accepted,
|
|
@@ -1234,31 +1252,33 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
|
|
|
1234
1252
|
...(reask === undefined ? {} : { reviewReask: reask }),
|
|
1235
1253
|
...(submission === undefined ? {} : { gateReviewInstruction: submission }),
|
|
1236
1254
|
});
|
|
1237
|
-
const officerSession = sessionFileFromPublicSummon(summoned);
|
|
1238
|
-
if (officerSession !== undefined) {
|
|
1239
|
-
bookDirectOfficerRunPointer({
|
|
1240
|
-
parentSessionFile: sessionFile, officer: "auditor", sessionFile: officerSession,
|
|
1241
|
-
submissionToolCallId: toolCallId,
|
|
1242
|
-
...(summoned.runDirectory === undefined ? {} : { runDirectory: summoned.runDirectory }),
|
|
1243
|
-
});
|
|
1244
|
-
}
|
|
1245
1255
|
lastSummon = summoned;
|
|
1256
|
+
const officerDir = summoned.runDirectory ?? summoned.admitted?.runDirectory;
|
|
1257
|
+
if (officerDir !== undefined && toolCallId.length > 0) {
|
|
1258
|
+
persistAdmittedAuditedSubmissionToolCallId(officerDir, toolCallId);
|
|
1259
|
+
}
|
|
1246
1260
|
return summoned;
|
|
1247
1261
|
},
|
|
1248
1262
|
});
|
|
1249
1263
|
if (decision.status === "continue") {
|
|
1250
1264
|
return runPublicInstructionSeatResume({
|
|
1251
|
-
runId: admitted.runId,
|
|
1265
|
+
runId: admitted.runId,
|
|
1266
|
+
runDirectory: admitted.runDirectory,
|
|
1267
|
+
summons: { instruction: readableGateItem(decision.receipt ?? decision.violations) },
|
|
1252
1268
|
}, envForCourtContinue(env), io);
|
|
1253
1269
|
}
|
|
1254
1270
|
if (decision.status === "received") {
|
|
1255
1271
|
if (lastSummon?.terminal === undefined) {
|
|
1256
1272
|
throw new Error("doctor audit kept an unreadable reply with no terminal");
|
|
1257
1273
|
}
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
const terminal = await
|
|
1261
|
-
return {
|
|
1274
|
+
const officerAdmitted = lastSummon.admitted;
|
|
1275
|
+
const officerDir = officerAdmitted?.runDirectory ?? lastSummon.runDirectory ?? admitted.runDirectory;
|
|
1276
|
+
const terminal = await presentUnsettledOfficer(lastSummon.terminal, io, officerDir);
|
|
1277
|
+
return {
|
|
1278
|
+
exitCode: 0,
|
|
1279
|
+
...(officerAdmitted === undefined ? { admitted } : { admitted: officerAdmitted }),
|
|
1280
|
+
terminal,
|
|
1281
|
+
};
|
|
1262
1282
|
}
|
|
1263
1283
|
if (decision.status !== "converged") {
|
|
1264
1284
|
if (lastSummon?.terminal !== undefined) {
|
|
@@ -1280,7 +1300,6 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
|
|
|
1280
1300
|
...(env.hostAdapters === undefined ? {} : { hostAdapters: env.hostAdapters }),
|
|
1281
1301
|
});
|
|
1282
1302
|
let chain;
|
|
1283
|
-
let officerRunId = resumedOfficer?.runId;
|
|
1284
1303
|
const runGate = (subject) => requireSubmissionGate({
|
|
1285
1304
|
context,
|
|
1286
1305
|
subject,
|
|
@@ -1295,8 +1314,10 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
|
|
|
1295
1314
|
},
|
|
1296
1315
|
});
|
|
1297
1316
|
if (admitted.role === "judge") {
|
|
1317
|
+
// Same order as runJudgeGates — sole source JUDGE_GATES + gateOfficerForSubject.
|
|
1318
|
+
const judgeGateOrder = JUDGE_GATES.map(gateOfficerForSubject);
|
|
1298
1319
|
chain = await runJudgeGates({
|
|
1299
|
-
gateAlreadyConverged: async (subject) =>
|
|
1320
|
+
gateAlreadyConverged: async (subject) => gateSatisfied(gateOfficerForSubject(subject), judgeGateOrder),
|
|
1300
1321
|
runGate,
|
|
1301
1322
|
});
|
|
1302
1323
|
}
|
|
@@ -1307,14 +1328,13 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
|
|
|
1307
1328
|
? { kind: "secretariat_verdict" }
|
|
1308
1329
|
: { kind: "countersign_verdict" };
|
|
1309
1330
|
const officer = gateOfficerForSubject(subject);
|
|
1310
|
-
if (
|
|
1331
|
+
if (gateSatisfied(officer)) {
|
|
1311
1332
|
chain = { status: "converged", passes: [] };
|
|
1312
1333
|
}
|
|
1313
1334
|
else {
|
|
1314
1335
|
const pass = await runGate(subject);
|
|
1315
1336
|
if (pass === undefined)
|
|
1316
1337
|
throw new Error("audit gate returned no conclusion");
|
|
1317
|
-
officerRunId = pass.runId;
|
|
1318
1338
|
chain = {
|
|
1319
1339
|
status: pass.status,
|
|
1320
1340
|
passes: [{
|
|
@@ -1329,23 +1349,34 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
|
|
|
1329
1349
|
}
|
|
1330
1350
|
}
|
|
1331
1351
|
if (chain.status === "needs_reask") {
|
|
1332
|
-
const
|
|
1352
|
+
const pass = chain.passes.at(-1);
|
|
1353
|
+
const officerTerminal = pass?.terminal;
|
|
1333
1354
|
if (officerTerminal === undefined)
|
|
1334
1355
|
throw new Error("unreadable audit has no terminal result");
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1356
|
+
const officerRunDirectory = pass?.runDirectory;
|
|
1357
|
+
const officerRunId = pass?.runId
|
|
1358
|
+
?? (officerRunDirectory === undefined ? undefined : runIdFromRunDirectory(officerRunDirectory));
|
|
1359
|
+
if (officerRunId === undefined)
|
|
1360
|
+
throw new Error("unreadable audit has no resumable run identity");
|
|
1361
|
+
const officer = await loadResumablePublicRole(env.home, officerRunId, env.principalAuthority, officerRunDirectory === undefined ? undefined : { runDirectory: officerRunDirectory });
|
|
1362
|
+
const terminal = await presentUnsettledOfficer(officerTerminal, io, officer.admitted.runDirectory);
|
|
1363
|
+
return { exitCode: 0, admitted: officer.admitted, terminal };
|
|
1339
1364
|
}
|
|
1340
1365
|
if (chain.status === "escalate") {
|
|
1341
1366
|
const escalation = chain.passes.at(-1);
|
|
1367
|
+
const escalatedRunDirectory = escalation?.runDirectory;
|
|
1342
1368
|
const escalatedRunId = escalation?.runId
|
|
1343
|
-
?? (
|
|
1344
|
-
? undefined : runIdFromRunDirectory(
|
|
1369
|
+
?? (escalatedRunDirectory === undefined
|
|
1370
|
+
? undefined : runIdFromRunDirectory(escalatedRunDirectory));
|
|
1345
1371
|
if (escalatedRunId === undefined)
|
|
1346
1372
|
throw new Error("escalated audit has no resumable run identity");
|
|
1347
|
-
const officer = await loadResumablePublicRole(env.home, escalatedRunId, env.principalAuthority);
|
|
1348
|
-
|
|
1373
|
+
const officer = await loadResumablePublicRole(env.home, escalatedRunId, env.principalAuthority, escalatedRunDirectory === undefined ? undefined : { runDirectory: escalatedRunDirectory });
|
|
1374
|
+
// Prefer the officer terminal already returned. Re-settle only when absent.
|
|
1375
|
+
// Other-seat tables stay on the officer run — parent does not attach copies (#1195).
|
|
1376
|
+
let terminal = escalation?.terminal;
|
|
1377
|
+
if (terminal === undefined) {
|
|
1378
|
+
terminal = await trySettlePublicSeat(officer.admitted, env.principalAuthority, { ...await readCurrentCourt(officer.admitted.runDirectory), ...packageFaultScope(officer.admitted, env, io) });
|
|
1379
|
+
}
|
|
1349
1380
|
if (terminal === undefined)
|
|
1350
1381
|
throw new Error("escalated audit has no terminal result");
|
|
1351
1382
|
await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, officer.admitted.runDirectory);
|
|
@@ -1354,27 +1385,15 @@ async function auditSubmittedRole(turn, env, io, resumedOfficer, passedReceipt)
|
|
|
1354
1385
|
if (chain.status === "continue") {
|
|
1355
1386
|
return runPublicInstructionSeatResume({
|
|
1356
1387
|
runId: admitted.runId,
|
|
1388
|
+
runDirectory: admitted.runDirectory,
|
|
1357
1389
|
summons: { instruction: readableGateItem(chain.passes.at(-1)?.receipt) },
|
|
1358
1390
|
}, envForCourtContinue(env), io);
|
|
1359
1391
|
}
|
|
1360
|
-
if (admitted.role === "secretariat") {
|
|
1361
|
-
const pass = chain.passes.at(-1);
|
|
1362
|
-
const receipt = pass?.receipt ?? passedReceipt;
|
|
1363
|
-
if (receipt !== undefined) {
|
|
1364
|
-
await env.sessionAppender(env.principalAuthority, admitted.principal, SECRETARIAT_GATE_OFFICER_ENTRY_TYPE, {
|
|
1365
|
-
officer: "countersign", receipt,
|
|
1366
|
-
...(officerRunId === undefined ? {} : { runId: officerRunId }),
|
|
1367
|
-
});
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
1392
|
}
|
|
1371
|
-
// The turn already settled this court
|
|
1372
|
-
//
|
|
1373
|
-
// republish the same attempt.
|
|
1393
|
+
// The turn already settled this court. Gate does not project other-seat finals
|
|
1394
|
+
// onto the parent public terminal (#1195) — present this leg's own volume.
|
|
1374
1395
|
if (turn.terminal === undefined)
|
|
1375
1396
|
throw new Error(`audited ${admitted.role} submission did not settle`);
|
|
1376
|
-
|
|
1377
|
-
turn = { ...turn, terminal };
|
|
1378
|
-
await presentTerminal(terminal, { ...io, omitFailureStderrDiagnostic: true }, admitted.runDirectory);
|
|
1397
|
+
await presentTerminal(turn.terminal, { ...io, omitFailureStderrDiagnostic: true }, admitted.runDirectory);
|
|
1379
1398
|
return turn;
|
|
1380
1399
|
}
|
|
@@ -26,6 +26,13 @@ import { NotarySourceRunError, resolveNotarySourceRunLocator, } from "../notary-
|
|
|
26
26
|
import { CliUsageError } from "./cli-errors.js";
|
|
27
27
|
import { REJECTED_PUBLIC_SPELLINGS, createTypedOptionConsumer, evaluateAnalystModeOptionContract, optionsForOwner, resolveAnalystMode, } from "./option-definitions.js";
|
|
28
28
|
import { errorText, isRecord } from "../unknown-value.js";
|
|
29
|
+
/** Nonblank admitted source path, preserving its original bytes. */
|
|
30
|
+
export function admittedSourceRunPath(admitted) {
|
|
31
|
+
if (!isRecord(admitted))
|
|
32
|
+
return undefined;
|
|
33
|
+
const path = admitted.sourceRunPath;
|
|
34
|
+
return typeof path === "string" && path.trim() !== "" ? path : undefined;
|
|
35
|
+
}
|
|
29
36
|
/** Normalize admitted attachment records (caller path only; #1165). */
|
|
30
37
|
export function normalizeAdmittedAttachment(raw) {
|
|
31
38
|
if (typeof raw !== "object" || raw === null)
|
|
@@ -174,6 +181,34 @@ export async function persistAdmittedSourceRunPath(admitted, sourceRunPath, audi
|
|
|
174
181
|
};
|
|
175
182
|
});
|
|
176
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* #1195 option 1: record the parent sealed toolCallId this officer is reviewing
|
|
186
|
+
* on the officer's own admitted-request (one field). Re-summons for a newer seal
|
|
187
|
+
* replace the value; continueParentAfterChild only trusts a child whose field
|
|
188
|
+
* matches the parent seal currently under audit.
|
|
189
|
+
*/
|
|
190
|
+
export function persistAdmittedAuditedSubmissionToolCallId(runDirectory, auditedSubmissionToolCallId) {
|
|
191
|
+
const id = auditedSubmissionToolCallId.trim();
|
|
192
|
+
if (id === "") {
|
|
193
|
+
throw new Error("persistAdmittedAuditedSubmissionToolCallId requires a non-empty id");
|
|
194
|
+
}
|
|
195
|
+
// Offline gate mocks may return a runDirectory without admission — skip, do not invent.
|
|
196
|
+
if (readPageSync(runDirectory, "admitted") === undefined)
|
|
197
|
+
return;
|
|
198
|
+
updateSectionSync(runDirectory, "admitted", (current) => {
|
|
199
|
+
if (current.auditedSubmissionToolCallId === id)
|
|
200
|
+
return undefined;
|
|
201
|
+
return { ...current, auditedSubmissionToolCallId: id };
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
/** Read the sealed id this officer admitted-request last recorded (#1195). */
|
|
205
|
+
export function readAdmittedAuditedSubmissionToolCallId(runDirectory) {
|
|
206
|
+
const page = readPageSync(runDirectory, "admitted");
|
|
207
|
+
if (page === undefined)
|
|
208
|
+
return undefined;
|
|
209
|
+
const id = page.auditedSubmissionToolCallId;
|
|
210
|
+
return typeof id === "string" && id.trim() !== "" ? id : undefined;
|
|
211
|
+
}
|
|
177
212
|
/**
|
|
178
213
|
* Bind a post-admission resolved ticketNumber onto the in-memory admitted
|
|
179
214
|
* object and both durable sections (invocation + admitted).
|